Gymterview
junior

Как работают условные выражения в bash?

Условные выражения в bash — это конструкции для проверки условий (существование файлов, сравнение строк и чисел, логические операции). Bash предоставляет три формы: test, [ ] (POSIX-совместимые) и [[ ]] (расширенная bash-конструкция).

test и [ ] — POSIX-совместимые конструкции

test и [ ] — это одно и то же ([ — это программа, ] — обязательный последний аргумент):

Пример
test -f file.txt       # Эквивалентно:
[ -f file.txt ]        # Между [ и ] обязательны пробелы!

[[ ]] — расширенная конструкция bash (рекомендуется)

[[ ]] — встроенная конструкция bash, более безопасная и мощная:

Пример
[[ -f file.txt ]]      # Безопасна при пустых переменных, поддерживает glob и regex

Проверки файлов

Пример
[[ -f file.txt ]]      # Файл существует и является обычным файлом
[[ -d directory ]]     # Существует и является директорией
[[ -e path ]]          # Существует (любой тип)
[[ -r file.txt ]]      # Файл доступен для чтения
[[ -w file.txt ]]      # Файл доступен для записи
[[ -x script.sh ]]     # Файл исполняемый
[[ -s file.txt ]]      # Файл существует и не пуст
[[ -L link ]]          # Является символической ссылкой
[[ file1 -nt file2 ]]  # file1 новее file2 (newer than)
[[ file1 -ot file2 ]]  # file1 старше file2 (older than)

Сравнение строк

Пример
[[ "$str1" == "$str2" ]]    # Строки равны
[[ "$str1" != "$str2" ]]    # Строки не равны
[[ "$str1" < "$str2" ]]     # Лексикографически меньше
[[ -z "$str" ]]             # Строка пуста (zero length)
[[ -n "$str" ]]             # Строка не пуста (non-zero length)
[[ "$str" == *.java ]]      # Glob-паттерн (только в [[ ]])
[[ "$str" =~ ^[0-9]+$ ]]   # Регулярное выражение (только в [[ ]])

Сравнение чисел

Пример
[[ $a -eq $b ]]    # Равно (equal)
[[ $a -ne $b ]]    # Не равно (not equal)
[[ $a -lt $b ]]    # Меньше (less than)
[[ $a -le $b ]]    # Меньше или равно (less or equal)
[[ $a -gt $b ]]    # Больше (greater than)
[[ $a -ge $b ]]    # Больше или равно (greater or equal)

# Арифметическое сравнение (альтернатива — удобнее для чисел)
(( a == b ))
(( a > b ))
(( a < b ))

Логические операции

Пример
# В [[ ]] — внутри одной конструкции
[[ condition1 && condition2 ]]    # И (AND)
[[ condition1 || condition2 ]]    # ИЛИ (OR)
[[ ! condition ]]                 # НЕ (NOT)

# В [ ] — через отдельные вызовы (другой синтаксис!)
[ condition1 ] && [ condition2 ]
[ condition1 ] || [ condition2 ]
[ ! condition ]

Сравнение [ ] и [[ ]]

Возможность [ ] [[ ]]
POSIX-совместимость Да Нет (только bash/zsh/ksh)
Glob-паттерны (*.java) Нет Да
Регулярные выражения (=~) Нет Да
&& / || внутри Нет Да
Безопасность при пустых переменных Требует кавычки Кавычки необязательны

Практический пример

Пример
#!/bin/bash
ENV="${1:-dev}"

if [[ "$ENV" =~ ^(dev|staging|production)$ ]]; then
    echo "Deploying to $ENV..."
else
    echo "Unknown environment: $ENV"
    echo "Usage: $0 [dev|staging|production]"
    exit 1
fi

if [[ -f "config-${ENV}.yml" ]]; then
    echo "Using config: config-${ENV}.yml"
else
    echo "Config not found, using defaults"
fi

На собеседовании: рекомендуйте [[ ]] как основную конструкцию, объясните преимущества: безопасность при пустых переменных, поддержка glob и regex, &&/|| внутри. Если спрашивают про POSIX-совместимость (скрипты для sh, а не bash), тогда используйте [ ].