When I was new to shell scripting, I used a lot of short tests instead of if
statements, like false && true
.
Then later I learned using set -e
, and found my scripts were dying for some reason, and they would work if I replaced the short tests with full if
statements. Now, the time has gone, and I still use full if
statements only.
The most interesting is that if I open an interactive shell and do the following:
set -e
false && true
echo $?
it returns 1 but the shell doesn't die!
I see that I have been wasting too many lines of code. Anyone could explain to me how can I use set -e
with short tests safely, eg. without the script dying?
You need to end each command which may fail with
||
and a command or command list evaluating to 0. Using||
will trigger your command if the expression before operator does not evaluate to 0. Your command needs to evaluate to 0 to not kill the shell.Example:
false && true
does not cause an exit because ending expression is evaluated and evaluates to 0. From the bash man page forset -e
:Only last command if executed in
||
/&&
chain can trigger exit.The following expression will fail from the reason above.
but the following will not:
because of
true && false
is part of test followingif
.Regarding my problem of the script unexpectedly dying, it is due to running those short tests in a subshell, or from a function, and said function returns a value different than zero:
Original example:
Using a subshell or function:
Possible solutions:
The Single UNIX Specification describes the effect of
set -e
as:As you see, a failing command in an AND list will not make the shell exit.
Using
set -e
Starting shell scripts with
set -e
is considered a best practice, since it is usually safer to abort the script if some error occurs. If a command may fail harmlessly, I usually append|| true
to it.Here is a simple example:
The behaviour of
set -e
is unintuitive in all but the simplest cases and has changed several times over the years. Therefore I do not recommend using it except in really simple scripts (plain sequences of commands).Note that commands in a Makefile are usually executed with
set -e
in effect, so it is still often needed to understand something about how it works.The
&&
and||
operators allow a similar effect with relatively little clutter, but make it explicit. In particular, a&&
might be placed at the end of a line much like a `;'.