I'd like to exit a script when an operation could not be executed.
non-existing || exit 1;
works fine and exits, while
ls || exit 1;
does not exit. Now, I'd also like to add an error message before exiting the program.
non-existing || echo "Having trouble" && exit 1;
exits as expected, but
ls || echo "Having trouble" && exit 1;
also exits, although the echo
command (and thus the exit
) should not be executed.
I first thought that using brackets might help:
ls || (echo "Having trouble" && exit 1;)
Does not exit. But when I invoke a non-existing program, the exit
-command only exits from the sub-shell that I opened using the brackets:
non-existing || (echo "Having trouble" && exit 1;)
echo "Still executed."
ls || echo "Having trouble" && exit 1;
exit?You can use { ...; }
instead of (...)
to avoid the subshell and the problem that causes and to get the result that you want.
Note that a space after the opening {
and a semicolon/etc. and a space before the closing }
are required for this (where they are optional with ()
).
As to why ls || echo && exit
doesn't do what you expect, the answer is because the ||
and &&
operators have the same precedence and are left-associative (see the POSIX specification).
So when the shell sees
ls || echo "Having trouble" && exit 1;
you think it is
ls || { echo "Having trouble" && exit 1; }
but the shell parses it as
{ ls || echo "Having trouble"; } && exit 1;
Or, as the specification puts it:
The operators "&&" and "||" shall have equal precedence and shall be evaluated with left associativity. For example, both of the following commands write solely bar to standard output:
false && echo foo || echo bar
true || echo foo && echo bar