Bash

zsh 和 POSIX 等效於 bash 的 {var}>&1

  • October 2, 2018

有相當於{var}>&1inzsh嗎?

bash手冊說:

每個可能以文件描述符編號開頭的重定向都可能以 形式的單詞開頭{varname}>&-在這種情況下,對於除and之外的每個重定向運算符<&-,shell 將分配一個大於 10 的文件描述符並將其分配給{varname}. 如果>&-or<&-前面有{varname},則 varname 的值定義要關閉的文件描述符。

一個範例用法是STDERR從命令中擷取:

{ error=$( { { ls -ld /XXXX /bin | tr o Z ; } 1>&$tmp ; } 2>&1); } {tmp}>&1

zsh在 POSIX 領域和在 POSIX 領域中如何做同樣的事情?

我正在尋求通用解決方案,我該如何:

  • 查找未使用的文件描述符
  • 模擬{var}>&1語法

支持{var}>...已添加到ksh93bash同時zsh根據zsh開發人員的建議。{var}>...運算符適用於,zsh但不適用於復合命令。

另請注意,在:

cmd 3>&1

fd 3 僅對cmd, 在

cmd {var}>&1

動態分配的 fd(儲存在 中)在和中返回$var後保持打開狀態。該運算符主要設計用於與系統呼叫一起使用(另請參見系統呼叫的更直接介面)。cmd``zsh``bash``exec``sysopen``zsh``open()

因此,您上面的程式碼缺少exec {tmp}>&-以後在bash.

所以在這裡你可以這樣做:

if exec {tmp}>&1; then
  errors=$(exec 2>&1 >&"$tmp" {tmp}>&- && ls -ld /x /bin | tr o Z)
  exec {tmp}>&-
fi

哪個可以工作bashzsh並且ksh93不會洩漏 fd。(僅在未啟用其選項$tmp時才需要引號)。請注意,在 POSIX 模式中或當或處於 POSIX 模式時,失敗會導致 shell 退出(此處失敗可能是由於標準輸出已關閉或達到打開文件數量的限製或您可能想要退出的其他病理情況)。bash``posix``ksh93``zsh``bash``exec``dup()

但是在這裡,您不需要動態分配的 fd,只需使用 fd 3,例如該程式碼中未使用的 fd 3:

{ errors=$(exec 2>&1 >&3 3>&-; ls -ld /x /bin | tr o Z); } 3>&1

這可以在任何類似 Bourne 的 shell 中工作。

就像上面的動態 fd 方法一樣,即使它不那麼明顯,如果dup2()(in 3>&1) 失敗,分配將不會執行,因此您可能需要確保errors在之前初始化(unset -v errors例如使用 a )。

請注意,fd 3 是否以其他方式打開或在腳本的其餘部分中使用並不重要(如果打開的原始 fd 將保持不變並在最後恢復),重要的是您是否嵌入了程式碼在$(...)期望 fd 3 內部打開。

只有 fds 0、1 和 2 預計會被應用程序打開,其他 fds 則不會。ls並且tr不要對 fd 3 抱有任何期望。您可能需要使用不同的 fd 的情況是,當您的程式碼明確使用該 fd 並期望它已經預先打開時,例如 if 而不是ls,您有cat /dev/fd/3fd 3 預期的位置已在腳本中較早的地方對某些資源開放。

要回答有關如何在 POSIX shell 中分配第一個免費 fd 的問題,我認為 POSIX shell 和實用程序 API 沒有辦法。這也可能沒有意義。shell 可以在內部使用任何不妨礙其自己 API 的 fd 做它想做的事情。例如,您可能會發現 fd 11 現在是免費的,但以後可能會被 shell 用於內部的某些內容,而您對其進行寫入可能會影響其行為。另請注意,在 POSIX sh 中,您只能操作 fds 0 到 9。

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