Команда test и [[expr]]

В командном языке bash операторы if и while могут использовать в качестве условия код завершения произвольной программы. Код ответа 0 интерпретируется как "истина", любой другой - как "ложь". Вместо if можно использовать операторы условного выполнения cmd1 && cmd2 - выполнить cmd2 если cmd1 завершилась успешно и cmd1 || cmd2 - выполнить cmd2 если cmd1 завершилась неуспешно.

Пример:

if grep --silent aaa file; then echo file \"file\" contain \"aaa\"; fi
grep --silent aaa file && echo file \"file\" contain \"aaa\"
grep --silent aaa file || echo file \"file\" not contain \"aaa\"

Для того, чтобы в качестве условия можно было бы писать традиционные выражения, была придумана команда test. Команда получает операторы и операнды в виде отдельных аргументов командной строки, вычисляет логическое условие и возвращает 0, 1 или 2 (в случае синтаксической ошибки).

Пример:

test "abc" = "cde" || echo "abc" not equal "cde"

Для красоты записи программа test имеет ещё одно имя - [ и вспомогательный последний аргумент ] . Две строчки ниже эквивалентны:

if test 1 -gt 0; then echo 1 \> 0;fi
if [ 1 -gt 0 ]; then echo 1 \> 0;fi

Аргументы команды test подвергаются обычным подстановкам и разбиением на слова, что часто приводит к ошибкам:

[ "A" > "B" ]       # неправильно
[ "A" \> "B" ]      # правильно
[ $A = HELLO ]      # ошибка если переменная A не определена, содержит пробелы или символы подстановки
[ "$A" = HELLO ]    # ошибка если $A начинается с минуса. Например -eq
[ x"$A" = xHELLO ]  # прием, позволяющий корректно провести сравнение

Для того, чтобы преодолеть указанные проблемы в язык введена синтаксическая конструкция [[expr]], которая разбирает выражение expr по тем же правилам, что и команда test, но при этом внутри скобок не производится подстановка имен файлов, перенаправление ввода/вывода и разбиение содержимого переменных на слова.

[[expr]] в отличие от [ expr ] не является независимой командой, что можно увидеть на примерах:

\[ -e file \]        # нормально
[ -e file ]          # то же самое
\[\[ -e file \]\]  # [[: command not found
[[ -e file ]]       # нормально

Набор операторов test и [[

Проверки объектов файловой системы: op path

  • -e объект существует
  • -f это файл
  • -s файл не нулевого размера
  • -d каталог
  • -b блочное устройство (например диск)
  • -c байтовое устройство (например модем)
  • -p именованный канал
  • -h -L символический линк
  • -S сокет

  • -r доступен на чтение

  • -w доступен на запись
  • -x доступен на выполнение

Проверка строк: op string

  • -z пустая строка
  • -n непустая строка

Сравнение строк: string1 op string2

  • = равны
  • != неравны
  • > больше
  • < меньше

Сравнение чисел: num1 op num2

  • -eq равны
  • -ne неравны
  • -gt больше
  • -lt меньше

Группировка: (expr)

Отрицание: ! expr

Логические операции в test: expr1 op expr2

  • -a И
  • -o ИЛИ

Логические операции в [[: expr1 op expr2

  • && И
  • || ИЛИ