I have a sequence of commands I want to run in such a way that when any command fails, the rest of the commands should no longer be executed. Let's assume the sequence of commands is
echo foo
false
echo bar
(i.e., I want foo
to be echoed but not bar
).
This should happen within a script that is run with set -e
, which I don't want to fail in its entirety if the above sequence of commands fails. My initial idea was to use a subshell
( echo foo ; false ; echo bar ; ) || true
but that doesn't work, both foo
and bar
are printed, because per the POSIX spec, set -e
loses its effect on the left-hand side of ||
, same as within an if
condition (I think this portion of the spec is conceptually flawed because it breaks abstraction, but oh well, no changing the POSIX specs now). An explicit set -e
within the parentheses cannot fix this either.
I also cannot do set +e ... set -e
around this portion, because instead of || true
I would want to run some alternative command that might fail and should cause the script to fail. (Besides that, restoring state via explicit set
commands is ugly.)
So it would seem I'm left with either set +e
+ explicit checking of $?
afterwards, or running the sequence of commands as a separate script (either in a separate file, or via bash <<EOF ...
), with the downside of not being able to access (array) variables easily.
Frankly, this seems like a fairly regular use case that the implicit and forced +e
within left-hand sides within expressions used as conditions makes disproportionately and surprisingly hard. Is there any easy option I'm missing?
sh -ec 'echo foo ; false ; echo bar' || true