test 或 [ 或 [[ 在 bash shell 和其他 shell 之間更可移植嗎?

test 或 [ 或 [[ 在 bash shell 和其他 shell 之間更可移植嗎?

我知道我能做到

$ [ -w /home/durrantm ] && echo "writable"
writable

或者

$ test -w /home/durrantm && echo "writable"
writable

或者

$ [[ -w /home/durrantm ]] && echo "writable"
writable

我喜歡使用第三種文法。它們在所有方面以及所有負面和邊緣情況下都是等價的嗎?可攜性是否有任何差異,例如 Ubuntu 上的 bash 和 OS X 或舊/新 bash 版本(例如 4.0 之前/之後)之間的差異,它們是否都以相同的方式擴展表達式?

答案1

是的,存在差異。最便攜的是test[ ]。這些都是POSIXtest規範

構造if ... fi也是由 POSIX 定義並且應該是完全便攜的。

[[ ]]功能ksh也存在於某些版本中bash所有現代的),在其他 shell 中zsh,也許在其他 shell 中,但不存在於shdash或其他各種較簡單的 shell 中。

因此,為了使您的腳本可移植,請使用[ ],testif ... fi.

答案2

[是命令的同義詞test,同時也是bash 內建和單獨的命令。但是[[是一個bash 關鍵字並且僅適用於某些版本。因此,出於可移植性的原因,您最好使用單一[]test

[ -w "/home/durrantm" ] && echo "writable"

答案3

請注意,這與建築[] && cmd不同。if .. fi

有時它的行為非常相似,您可以[] && cmd使用if .. fi.但只是有時。如果您有多個命令要執行 if 條件,或者您需要if .. else .. fi小心並了解其邏輯。

舉幾個例子:

[ -z "$VAR" ] && ls file || echo wiiii

不一樣

if [ -z $VAR ] ; then
  ls file
else
  echo wiii
fi

因為 ifls會失敗,echo將會被執行,而 . 不會發生這種情況if

另一個例子:

[ -z "$VAR" ] && ls file && echo wiii

不等於

if [ -z "$VAR" ] ; then
   ls file
   echo $wiii
fi

雖然這個結構的作用是一樣的

[ -z "$VAR" ] && { ls file ; echo wiii ; }

請注意;echo 很重要且必須存在。

所以繼續上面的陳述我們可以說

[] && cmd== 如果第一個指令成功則執行下一個指令

if .. fi== if 條件(也可能是測試指令)然後執行指令

因此僅用於之間的移植[[[使用[

if與 POSIX 相容。因此,如果您必須在兩者之間做出選擇[if請考慮您的任務和預期行為。

答案4

為了便於移植,請使用test/ [。但是,如果您不需要可移植性,為了您自己和其他人閱讀您的腳本的理智,請使用[[. :)

另請What is the difference between test, [ and [[ ?參見Bash常見問題解答

相關內容