Nushell - CrossPlatformlqip

Nushell - CrossPlatform

在Bash中,可以通过 $OSTYPE 这个Bash Variable[1]判断系统信息:

BASH
case "$OSTYPE" in  solaris*) echo "SOLARIS" ;;  darwin*)  echo "OSX" ;;  linux*)   echo "LINUX" ;;  bsd*)     echo "BSD" ;;  msys*)    echo "WINDOWS" ;;  # via Git Bash/msysGit  cygwin*)  echo "ALSO WINDOWS" ;; # via Cygwin  *)        echo "unknown: $OSTYPE" ;;esac

其对Windows的判断有点麻烦;可以用 uname 程序代替,不过这就引入了新依赖。

Nushell作为相对现代的Shell,这点上做的便利一些,它在 $nu[2] 常量里的 os-info 字段中记录了OS相关的信息,包括系统名称,架构 etc.

NU
# 打印 $nu.os-info╭────────────────┬─────────╮ name            macos    arch            aarch64  family          unix     kernel_version  25.1.0  ╰────────────────┴─────────╯

Demos

使用该字段作为条件,可以方便的编写跨平台函数/脚本,也方便针对不同平台编写对应的配置

Cross-Platform Functions/Scripts

不同系统的基础命令存在差异(如打开文件管理器),可以通过 match $nu.os-info.name 封装统一接口,屏蔽平台差异。

以打开文件管理器为例,Windows下要使用 explorer.exe,而MacOS则为 Finder.app;可以编写如下函数实现用平台默认的文件管理器打开指定文件夹

NU
config.nu
def omni-open [path: string = "."] {  let path = ($path | path expand)  match $nu.os-info.name {    macos => { ^open $path }    windows => { explorer.exe $path }    linux => { ^xdg-open $path } # not tested  }}alias o = omni-open

BTW,Nushell built-in的 start 命令其实实现了上面函数的功能,还支持打开URL,obsidian vault etc.

不同OS下剪贴板命令也不一样,macOS下使用 pbcopy ,Windows下使用 clip;可以编写如下函数实现跨平台复制文本到剪贴板

NU
config.nu
def copy_text [] {  match $nu.os-info.name {    "windows" => {      # Windows 使用 clip 命令      $in | ^clip    }    "macos" => {      # macOS 使用 pbcopy 命令      $in | ^pbcopy    }  }}

使用场景:

NU
# 复制当前路径pwd | copy_text# 复制某个文件的内容open README.md | copy_text

不同平台设置环境变量的方式也不一样,macos下使用 launchctl setenv,windows下使用 setx,linux的话可以将环境变量写入到 /etc/profile.d/**.sh 里,具体可以参考 Unix环境变量。这里可以编写一个Nushell funciton封装不同OS的差异

NU
def --env env [name: string value: string] {  # Set env var for current session  load-env {$name: $value}  match $nu.os-info.name {    "macos" => {      /bin/launchctl setenv $name $value    }    "linux" => {      let env_file = "/etc/profile.d/gnix-env.sh"      touch $env_file      chmod +x $env_file      let lines = (open $env_file | lines | where not ($it | str starts-with $"export ($name)="))      let env_value = ($value | str replace $nu.home-path "$HOME")      let updated = ($lines | append $"export ($name)=\"($env_value)\"")      $updated | str join (char nl) | save --force $env_file    }    "windows" => {      setx $name $value    }  }}

OS-Specific Configs

Shell里配置文件通常会包含OS-specific的内容,比如Windows下的Scoop别名,macOS下的Homebrew补全脚本等,此外PATH的设置也会因系统而异。

对于该问题,可以在 config.nu 里通过条件判断实现

Step 1: OS-specific Config

以 Windows 为例,创建platform/win.nu存放专属配置

NU
platform/win.nu
$env.YAZI_FILE_ONE = 'D:/envir_vars/scoop/apps/git/current/usr/bin/file.exe'source ../aliases/scoop.nusource ../completions/scoop.nusource ../completions/winget.nudef --env pwd [] { $env.PWD | str replace --all '\' '/'}alias su = scoop updatealias si = scoop installalias sui = scoop uninstallalias sse = scoop searchalias sst = scoop statusalias sl = scoop listalias sbl = scoop bucket listalias sba = scoop bucket addalias sbr = scoop bucket rmalias sui = scoop uninstallalias cdc = cd c://alias cdd = cd d://alias cde = cd e://

Step 2: Conditional Load

config.nu 里这样写,这里用到了Nushell里 source null[3] 为no-op(no operation) 的feature

NU
config.nu
const window_module = if $nu.os-info.name == windows { "./platform/win.nu" } else { null }const mac_module = if $nu.os-info.name == macos { "./platform/mac.nu" } else { null }source $window_modulesource $mac_module

  1. See Bash Variables (Bash Reference Manual) ↩︎

  2. Special Variables | Nushell ↩︎

  3. source | Nushell In Nushell, Sourcing null is a no-op. ↩︎

Author

GnixAij

Posted on

2025-10-16

Updated on

2025-12-16

License under