Command-Substitution

fish shell:為什麼filewhich command`在zsh和bash中有效,但在fish中無效?

  • June 1, 2022

在切換到 fish shell 之前,我經常在zshwith中使用各種命令which some_command。一個例子可能是:

$ file `which zsh`
/opt/local/bin/zsh: Mach-O 64-bit executable arm64
/bin/zsh:           Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit executable x86_64
- Mach-O 64-bit executable x86_64] [arm64e:Mach-O 64-bit executable arm64e
- Mach-O 64-bit executable arm64e]
/bin/zsh (for architecture x86_64): Mach-O 64-bit executable x86_64
/bin/zsh (for architecture arm64e): Mach-O 64-bit executable arm64e

當我嘗試使用fish它失敗時:

$ which zsh
/opt/local/bin/zsh

$ file `which zsh`
`which: cannot open ``which' (No such file or directory)
zsh`:   cannot open `zsh`' (No such file or directory)

fish知道為什麼這與其他更像 bash 的 shell 相比不起作用嗎?

fish 不使用反引號進行命令替換。相反,可以使用 parens: file (which zsh)or (in release 3.4.0 and later) file $(which zsh)。這些意思是一樣的。

查看bash 使用者的 fish 以了解其他差異。

FWIW,在 中zsh,您寧願使用:

file -- =zsh

或者:

() {file -- $1:c} zsh

file $(which zsh)(deprecated 的現代版本file which zsh``)只有在沒有定義別名或函式zsh並且 zsh 命令的路徑既不以換行符開頭-也不以換行符結束且不包含$IFS(space, tab , newline 和 nul 預設)。

file -- "$(whence -p zsh)"

會更正確(which作為, forzsh的別名,最初是 csh 使用者的 csh 腳本)。whence -c``-c``csh``which

fish中,正如fish’s 的維護者已經說過的那樣,命令替換是在最近的版本中(...)或也在$(...)最近的版本中(後者可以在雙引號內使用)。

相反zsh,fish沒有which內置的,所以行為會隨著你所在的系統而變化,這which是一個非標準的,經常被破壞的命令

fish有一個type內置命令,雖然它支持一個-P選項來強制$PATH像 zsh’s 這樣的查找whence -p

預設情況下,命令替換按換行符拆分。但是,如果使用$(...)內部雙引號,則不會拆分,但會刪除所有尾隨換行符。

因此fish,更正確的版本是:

file -- "$(type -P zsh)"

或舊版本:

file -- (type -P zsh | string collect)

(與 的不同之處"$(...)"在於,如果type不產生輸出(或僅產生換行符),它將不會傳遞任何參數file而不是一個空參數)。


¹which zsh要返回以換行符結尾的內容,例如,您需要這樣做hash zsh=$'/path/to/some/fileendinginnewline\n\n',這在這裡很做作。

引用自:https://unix.stackexchange.com/questions/704534