I've run across some scripting like this recently:
( set -e ; do-stuff; do-more-stuff; ) || echo failed
This looks fine to me, but it does not work! The set -e
does not apply, when you add the ||
. Without that, it works fine:
$ ( set -e; false; echo passed; ); echo $?
1
However, if I add the ||
, the set -e
is ignored:
$ ( set -e; false; echo passed; ) || echo failed
passed
Using a real, separate shell works as expected:
$ sh -c 'set -e; false; echo passed;' || echo failed
failed
I've tried this in multiple different shells (bash, dash, ksh93) and all behave the same way, so it's not a bug. Can someone explain this?
Best Answer
According to this thread, it's the behavior POSIX specifies for using "
set -e
" in a subshell.(I was surprised as well.)
First, the behavior:
The second post notes,
There's a little more in the fourth post, also by Eric Blake,
This behavior is definitely surprising. It is counter-intuitive: one would expect the re-enabling of
set -e
to have an effect, and that the surrounding context would not take precedent; further, the wording of the POSIX standard does not make this particularly clear. If you read it in the context where the command is failing, the rule does not apply: it only applies in the surrounding context, however, it applies to it completely.