Проверить аргумент скрипта
$# — число аргументов. Переменные в проверке — в двойных кавычках: имя файла
с пробелом останется одним аргументом.
test и [ ] проверяют файл, строку или число и отвечают кодом: 0 — да, 1 — нет; [[ ]] — их версия в bash.
[ -f /etc/app.conf ] && echo "файл есть"
[ -d "$dir" ] || mkdir -p "$dir"
[ -z "$1" ] && { echo "Usage: $0 FILE" >&2; exit 2; }
[ "$answer" = yes ]
строки равны
[ "$count" -gt 10 ]
число больше 10
[ -r "$f" ] && [ -s "$f" ]
читается и не пустой
[[ $name == *.log ]]
шаблон, только bash
[[ $ver =~ ^[0-9]+\.[0-9]+$ ]]
регулярное выражение, только bash
test проверяет условие и ничего не печатает — отвечает
кодом завершения: 0 — условие верно, 1 — нет, 2 — ошибка в самом
выражении. [ — та же команда под другим именем, последним аргументом она ждёт
]. Поэтому пробелы вокруг скобок обязательны: каждая часть выражения —
отдельный аргумент.
[[ ]] — ключевое слово bash: выражение разбирает сама оболочка, до подстановки
переменных. Поэтому внутри [[ ]] переменная без кавычек не распадается на
слова, < и > не становятся перенаправлением, а == сравнивает с шаблоном.
В sh (dash) [[ ]] нет: скрипт с #!/bin/sh обходится [ ].
[ ] и test |
[[ ]] |
|
|---|---|---|
| где работает | любая POSIX-оболочка | bash и zsh |
$x без кавычек |
делится на слова — ошибки | безопасно |
шаблон *.log |
нет | ==, != |
| регулярное выражение | нет | =~ |
| два условия | [ a ] && [ b ] |
[[ a && b ]] |
Проверки бывают трёх видов:
-e существует, -f обычный файл, -d каталог, -L символическая
ссылка, -r, -w, -x — право текущего пользователя, -s файл не пустой,
a -nt b — a новее b;= (в bash и ==), !=, -z — пустая, -n — не пустая;-eq, -ne, -lt, -le, -gt, -ge.! перед проверкой обращает её: [ ! -f "$f" ] — файла нет.
< и > сравнивают строки посимвольно: [[ 10 > 9 ]] ложно, потому что «1»
идёт раньше «9». Числа сравнивай через -gt, -lt или (( )).
Проверки test — в таблице ниже. Полный список — help test, у [[ ]] —
man bash, раздел CONDITIONAL EXPRESSIONS.
| Ключ | Что делает | Пример |
|---|---|---|
-e FILE |
Файл существует (любой тип); битая ссылка — нет. | [ -e /etc/app.conf ] |
-f FILE |
Обычный файл — не каталог и не устройство. | [ -f "$1" ] || exit 1 |
-d DIR |
Каталог. | [ -d /srv/backup ] || mkdir -p /srv/backup |
-r / -w / -x FILE |
Текущему пользователю можно читать, писать, запускать. | [ -w "$dir" ] |
-z / -n STRING |
Строка пустая / не пустая; переменную — в кавычках. | [ -z "$1" ] |
= / != A B |
Строки равны / не равны; в bash можно и ==. | [ "$answer" = yes ] |
-eq / -ne A B |
Целые числа равны / не равны. | [ $# -eq 1 ] |
-lt / -le / -gt / -ge A B |
Меньше, не больше, больше, не меньше. | [ "$used" -ge 90 ] |
-s FILE |
Файл существует и не пустой. | [ -s report.txt ] |
-L FILE |
Символическая ссылка — даже если цели нет. | [ -L /etc/localtime ] |
! EXPR |
Обратить проверку. | [ ! -f "$lock" ] |
[[ == ]] PATTERN |
Строка подходит под шаблон с * и ?; шаблон без кавычек. | [[ $file == *.log ]] |
[[ =~ ]] REGEX |
Строка подходит под регулярное выражение; группы — в BASH_REMATCH. | [[ $ver =~ ^[0-9]+\.[0-9]+$ ]] |
-nt / -ot A B |
Файл A новее (старше) файла B по времени изменения. | [ app.conf -nt app.conf.bak ] |
-a / -o |
«И», «или» внутри [ ]; устарели — пиши [ a ] && [ b ]. | [ -d /tmp ] && [ -w /tmp ] |
Ничего не найдено. Попробуй запрос короче.
$# — число аргументов. Переменные в проверке — в двойных кавычках: имя файла
с пробелом останется одним аргументом.
-ge ждёт голое число. tr -dc '0-9' убирает пробелы и знак %, иначе
проверка падает с integer expression expected.
Для day=2026-10-20 второе условие напечатает год 2026, месяц 10: скобки
выражения попадают в массив BASH_REMATCH. Правую часть не бери в кавычки:
[[ app.log == "*.log" ]] сравнивает буквально и даёт 1.
Переменная пустая и стоит без кавычек: [ $x = foo ] превратилось в
[ = foo ]. Пиши [ "$x" = foo ].
В значении пробел: при x="a b" проверка [ $x = foo ] получила a, b, =,
foo. Возьми переменную в кавычки или перейди на [[ ]].
-eq, -gt и соседям досталось не число: пустая строка, 85%, слово. Выведи
значение (echo "[$used]") и очисть его до цифр.
Нет пробела после [ или перед ]. [-f оболочка ищет как имя команды, а
[ -f file] не находит последний аргумент ].
Так sh (dash) отвечает на == внутри [ ]. В POSIX строки сравнивает =.
Либо пиши =, либо запускай скрипт в bash: #!/bin/bash в первой строке.
Без кавычек пустое значение исчезает, остаётся [ -n ] — проверка непустой
строки -n, и она верна. С кавычками [ -n "$x" ] даёт 1, как и ждёшь.
[[ 08 -eq 8 ]] и (( 08 )) читают число с нулём впереди как восьмеричное, а
8 и 9 в нём нет. Так ломаются месяц и день из date +%m. Пиши 10#$m или
сравнивай в [ ]: там 08 — обычное десятичное.
-e и -f смотрят на файл, куда ведёт ссылка. Если цели нет, проверка
ложна. Саму ссылку проверяет -L.
Внутри [ ] знак > — перенаправление. Оболочка создаёт в
текущем каталоге пустой файл 9, а проверка сводится к [ 10 ] и верна
всегда — даже [ 1 > 9 ]:
Числа сравнивай через -gt.
Между [ -f "$lock" ] и созданием файла другой экземпляр скрипта успеет
сделать то же самое. Для защиты от двойного запуска нужна блокировка —
flock.
&&, ||.if, циклы и аргументы скрипта.* и ?, те же, что в [[ == ]].=~.r, w, x для -r, -w, -x.[ ].Есть неточность? Сообщить об ошибке в статье