Является ли test или [ или [[ более переносимым как между оболочками bash, так и между другими оболочками?

Является ли test или [ или [[ более переносимым как между оболочками bash, так и между другими оболочками?

Я вижу, что я могу сделать

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

или

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

или

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

Мне нравится использовать третий синтаксис. Они эквивалентны во всех отношениях и для всех отрицательных и крайних случаев? Есть ли какие-либо различия в переносимости, например, между bash на Ubuntu и на OS X или более старыми/новыми версиями bash, например, до/после 4.0, и расширяют ли они выражения одинаково?

решение1

Да, есть различия. Наиболее переносимыми являются testили [ ]. Они оба являются частьюtestСпецификация POSIX.

Конструкция if ... fiтакжеопределено POSIXи должен быть полностью портативным.

Эта [[ ]]функция kshтакже присутствует в некоторых версиях bash(все современные), в zshи, возможно, в других, но не присутствует в shили dashили различных других более простых оболочках.

Итак, чтобы сделать ваши скрипты переносимыми, используйте [ ], testили if ... fi.

решение2

[является синонимом команды testи одновременновстроенный bashи отдельное командование. Но [[этоключевое слово bashи работает только в некоторых версиях. Поэтому по соображениям портативности лучше использовать один []илиtest

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

решение3

Обратите внимание, что [] && cmdэто не то же самое, что if .. fiстроительство.

Иногда его поведение довольно похоже, и вы можете использовать [] && cmdего вместо if .. fi. Но только иногда. Если у вас есть более одной команды для выполнения, если условие или вам нужно if .. else .. fiбыть осторожным и следить за логикой.

Пара примеров:

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

Это не то же самое, что

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

потому что если lsпроизойдет сбой, 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совместим с POSIX. Так что если вам нужно выбрать между [и ifвыбрать, глядя на вашу задачу и ожидаемое поведение.

решение4

Для переносимости используйте test/ [. Но если вам не нужна переносимость, ради вашего спокойствия и спокойствия других, читающих ваш скрипт, используйте [[. :)

Также см. What is the difference between test, [ and [[ ?вBashFAQ.

Связанный контент