17

I use set -e to stop bash script on first error.

All work OK unless I use command with &&:

$ 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
$

compared with:

$ 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
$

The first example still echoes I'm running!, but the second one doesn't. Why do they behave differently?

UPD. Similar question: https://stackoverflow.com/questions/6930295/set-e-and-short-tests

4
13

This is documented behavior.  The bash(1) man page says, for set -e,

The shell does not exit if the command that fails is part of the command list immediately following a while or until keyword, part of the test following the if or elif reserved words, part of any command executed in a && or || list except the command following the final && or ||, any command in a pipeline but the last, or if the command's return value is being inverted with !.
[Emphasis added.]

And the POSIX Shell Command Language Specification confirms that this is the correct behavior:

The -e setting shall be ignored when executing the compound list following the while, until,if, or elif reserved word, a pipeline beginning with the ! reserved word, or any command of an AND-OR list other than the last.

and Section 2.9.3 Lists of that document defines

An AND-OR list is a sequence of one or more pipelines separated by the operators "&&" and "||" .

0
10

The set -e option doesn't have effect in some situations, and this is the standard behavior and portable across POSIX compliant shell.


The failed command is part of pipeline:

false | true; echo printed

will print printed.

And only the failure of the pipeline itself is considered:

true | false; echo 'not printed'

will print nothing.


The failed command run in the compound list following the while, until, if, elif reserved word, a pipeline beginning with the ! reserved word, or any command as part of && or || list except the last one:

false || true; echo printed

The last command fails still make set -e affected:

true && false; echo 'not printed'

The subshell fails in a compound command:

(false; echo 'not printed') | cat -; echo printed
2
  • Thank you! It would be clearer to use echo "printed" and echo "not_printed" in your examples (instead of echo 1).
    – 907th
    Sep 27 '16 at 9:35
  • 3
    Note that set -e causes an exit in (false && true); echo not here, but not in { false && true; }; echo here, though YMMV with different shells and even different versions of a same shell. I wouldn't touch set -e with a barge pole and would do proper error handling instead. Sep 27 '16 at 13:47
2

my guess is if-then condition as a whole evaluate to true.

I tried

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

who give

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

error code is catch by if condition, thus bash will not trigger end of execution.

2
  • But I do not use if ... fi
    – 907th
    Sep 27 '16 at 9:27
  • I know, this is an implicit if.
    – Archemar
    Sep 27 '16 at 9:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.