basherror-handling

How can I exit a program with an error message and error code in Bash?


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."

Solution

  • 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