set и shopt
Режимы bash — set -euo pipefail, -x для отладки, noclobber, set -- и опции shopt для шаблонов
set и shopt — встроенные команды, которые включают и выключают режимы самой оболочки. Через set задают «строгий режим» скриптов (set -euo pipefail), трассировку команд (set -x) и позиционные аргументы (set -- …). Через shopt — поведение шаблонов *: пустой результат вместо самого шаблона, рекурсивный **, расширенные шаблоны. Справка — help set и help shopt.
Синтаксис
set -о # включить опцию (минус)
set +о # выключить опцию (плюс)
set -o имя # включить опцию по длинному имени; set +o имя — выключить
set -o # показать все опции и их состояние
set -- a b c # заменить позиционные аргументы $1 $2 $3
shopt -s имя # включить опцию shopt (set)
shopt -u имя # выключить (unset)
shopt имя # показать состояние
Опции действуют до конца текущей оболочки (скрипта). В шебанг их тоже можно вписать: #!/bin/bash -eu. Текущие короткие опции лежат в $-.
Опции set
| Короткая | Длинная (set -o …) | Что делает |
|---|---|---|
-e | errexit | завершить скрипт, как только команда вернула ненулевой код (есть исключения — см. ниже) |
-u | nounset | обращение к незаданной переменной — ошибка и выход |
pipefail | код пайплайна — код последней упавшей команды, а не только последней команды | |
-x | xtrace | печатать каждую команду перед выполнением (в stderr, с префиксом $PS4, по умолчанию + ) |
-v | verbose | печатать строки скрипта по мере чтения, до подстановок |
-C | noclobber | > не перезаписывает существующий файл; принудительно — >| |
-f | noglob | не раскрывать шаблоны *, ?, […] |
-n | noexec | только проверить синтаксис, ничего не выполнять (bash -n script.sh) |
-a | allexport | автоматически экспортировать все новые переменные |
-E | errtrace | ловушка trap … ERR срабатывает и внутри функций |
-T | functrace | ловушки DEBUG и RETURN срабатывают внутри функций |
-b | notify | сразу сообщать о завершении фоновых задач |
-m | monitor | управление заданиями (fg, bg); включено в интерактивной оболочке |
-h | hashall | запоминать пути найденных команд (включено по умолчанию) |
-B | braceexpand | раскрывать {a,b} и {1..5} (включено по умолчанию) |
posix | режим совместимости с POSIX | |
vi / emacs | режим редактирования командной строки |
Позиционные аргументы: set --
| Команда | Что делает |
|---|---|
set -- a "b c" d | $1=a, $2="b c", $3=d, $#=3 |
set -- | очистить все аргументы |
set -- "$@" новый | добавить аргумент в конец |
set -- $строка | разрезать строку по $IFS на аргументы (сознательно без кавычек) |
Опции shopt
| Опция | Что делает |
|---|---|
nullglob | шаблон без совпадений превращается в ничто, а не остаётся строкой *.txt |
failglob | шаблон без совпадений — ошибка no match, команда не выполняется |
globstar | ** совпадает с файлами и каталогами на любой глубине: **/*.log |
dotglob | * включает скрытые файлы (имена с точки), кроме . и .. |
nocaseglob | шаблоны без учёта регистра |
extglob | расширенные шаблоны: !(…), @(…), +(…), *(…), ?(…) |
nocasematch | [[ == ]] и case без учёта регистра |
lastpipe | последняя команда пайплайна выполняется в текущей оболочке (работает в скриптах) |
inherit_errexit | $(…) наследует set -e |
expand_aliases | раскрывать алиасы в скрипте (по умолчанию только в интерактивной оболочке) |
login_shell | только чтение: включена, если оболочка — login shell |
Флаги shopt: -s включить, -u выключить, -q тихо проверить (код 0 — включено), -p вывести в виде команд, -o работать с опциями set -o.
Расширенные шаблоны (extglob)
| Шаблон | Совпадает |
|---|---|
!(шаблон) | со всем, что не совпадает с шаблоном: rm !(*.conf) |
@(a|b) | ровно с одним из вариантов: *.@(jpg|png) |
?(a) | ноль или один раз |
*(a) | ноль или больше раз |
+(a) | один или больше раз |
Примеры
#!/bin/bash
# «строгий режим» в начале скрипта
set -euo pipefail
# отладить кусок скрипта: включить трассировку и выключить обратно
set -x
cp /etc/hostname /tmp/
set +x
# понятный префикс трассировки: номер строки
PS4='+ ${LINENO}: '
set -x
# запустить скрипт с трассировкой, не меняя его
bash -x ./script.sh
# только проверить синтаксис
bash -n ./script.sh
# не затереть существующий файл случайным >
set -o noclobber
echo данные > /tmp/out.txt
echo новое > /tmp/out.txt # ошибка: cannot overwrite existing file
echo новое >| /tmp/out.txt # явная перезапись
# цикл по файлам, который не выполнится ни разу, если файлов нет
shopt -s nullglob
for f in /var/log/*.gz; do
echo "архив: $f"
done
# все .log на любой глубине
shopt -s globstar
ls /var/log/**/*.log
# все файлы, кроме .conf (extglob включай отдельной строкой до использования)
shopt -s extglob
ls /etc/!(*.conf)
# разобрать строку на поля и обращаться к ним как к $1, $2
set -- $(date '+%Y %m %d')
echo "год $1, месяц $2"
# незаданная переменная под set -u — со значением по умолчанию
echo "${DEBUG:-0}"
Подводные камни
set -eсрабатывает не везде. Ошибка игнорируется в условииif/while, слева от&&и||, после!, в любой команде пайплайна, кроме последней. Функция, вызванная какf || …, выполняется до конца, даже если команды внутри неё падают.$(…)подset -eне наследует-e.x=$(false; echo ok)дастx=ok. Включиshopt -s inherit_errexit.local x=$(cmd)иecho "$(cmd)"скрывают ошибкуcmd— код берётся отlocalилиecho. Отдельное присваиваниеx=$(cmd)подset -eскрипт завершит.((i++))приi=0подset -eзавершает скрипт — код возврата 1. Пишиi=$((i + 1)).- Без
pipefailошибка в начале пайплайна теряется.false | trueвозвращает 0. Сset -o pipefail— 1. set -uи пустые массивы."${arr[@]}"у объявленного пустого массива работает (bash 4.4+), а${#arr[@]}у необъявленного массива — ошибкаunbound variable. Для переменных, которых может не быть, пиши${VAR:-}.nullglobменяет поведение команд с пустым шаблоном.ls *.txtбез совпадений превращается вlsи показывает весь каталог. Включайnullglobв скриптах для циклов, а не глобально в~/.bashrc.extglobнужно включить на отдельной строке до шаблона. Bash разбирает строку целиком перед выполнением, поэтомуshopt -s extglob; ls !(*.log)на одной строке —syntax error near unexpected token '('.- Алиасы в скриптах не работают без
shopt -s expand_aliases: команда выдастcommand not found. В скриптах вместо алиасов пиши функции.
См. также
exit-codes · variables · functions · redirection · shellcheck · env