Скрипт Bash с `set -e` не останавливается на команде `... && ...`

Скрипт Bash с `set -e` не останавливается на команде `... && ...`

Я использую set -eдляостановить bash-скрипт при первой ошибке.

Все работает нормально, пока я не использую команду с &&:

$ cat script
set -e
cd not_existing_dir && echo 123
echo "I'm running! =P"
$
$ ./script
./script: line 2: cd: not_existing_dir: No such file or directory
I'm running! =P
$

по сравнению с:

$ cat script
set -e
cd not_existing_dir
echo "I'm running! =P"
$
$ ./script
./script: line 2: cd: not_existing_dir: No such file or directory
$

Первый пример еще эхом I'm running!, а второй нет. Почему они ведут себя по-разному?

UPD. Похожий вопрос:https://stackoverflow.com/questions/6930295/set-e-and-short-tests

решение1

Это задокументированное поведение.bash(1) страница руководстваговорит, дляset -e,

Оболочка не завершает работу, если команда, которая не выполняется, является частью списка команд, следующей сразу за ключевым словом whileили until, частью теста, следующей за зарезервированными словами ifили ,elifчасть любой команды, выполняемой в списке &&или|| за исключением команды, следующей за финальным &&или||, любая команда в конвейере, кроме последней, или если возвращаемое значение команды инвертируется с помощью !.
[Выделено мной.]

ИPOSIXЯзык команд оболочкиСпецификация подтверждает, что это правильное поведение:

Настройка -eбудет игнорироваться при выполнении списка составных элементов, следующего за зарезервированным словом while, until, if, или elifконвейером, начинающимся с !зарезервированного слова, или любой командой списка И-ИЛИ, кроме последней.

иРаздел 2.9.3Спискиэтого документа определяет

Список И-ИЛИ представляет собой последовательность одного или нескольких конвейеров, разделенных операторами « &&» и « ||».

решение2

В некоторых ситуациях эта set -eопция не действует, и это стандартное поведение, переносимое в оболочку, совместимую с POSIX.


Невыполненная команда является частью конвейера:

false | true; echo printed

будет напечатано printed.

И учитывается только выход из строя самого трубопровода:

true | false; echo 'not printed'

ничего не напечатает.


Невыполненная команда, запущенная в списке составных команд после зарезервированного слова while, until, if, elifконвейера, начинающегося с !зарезервированного слова, или любой команды как части &&списка ||, кроме последней:

false || true; echo printed

Последняя команда не выполняется, но все равно set -eвлияет:

true && false; echo 'not printed'

Theподоболочкане выполняется в составной команде:

(false; echo 'not printed') | cat -; echo printed

решение3

Я предполагаю, что условие if-then в целом оценивается как истинное.

Я пытался

set -e
if cd not_existing_dir
then  echo 123
fi
echo "I'm running! =P"

кто дает

-bash: cd: not_existing_dir: No such file or directory
I'm running! =P

Код ошибки перехватывается условием if, поэтому bash не вызовет завершение выполнения.

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