I am running my scripts with:
#!/bin/bash -eu
Which aborts the script whenever a problem occurs, as wanted. But sometimes I expect one of the commands to eventually fail, and I would like to tell bash
to ignore the fail condition. In make
you can ignore the status of one command with the handy:
-command
Is there something similar in bash
? The only thing that comes to mind is the ugly:
set +e
command
set -e
You could just do a no-op on the command failure or set an explicit true condition as
command || true
or for no-op as
command || :
Doing so forces the command-list (even a pipeline) to return an exit status of 0 on failure. See
true | false
echo $?
1
true | false || true
echo $?
0
true | false || :
echo $?
0
Just prepend a !
to the command so that its exit status does not make the script exit when running it with e
:
! command
As seen in What's the meaning of a ! before a command in the shell?, having ! command
negates the exit status of the given command and, used with set -e
, prevents the shell to exit whatever the exit result is on that line.
From Bash Reference Manual → Pipelines:
Each command in a pipeline is executed in its own subshell. The exit status of a pipeline is the exit status of the last command in the pipeline (...). If the reserved word ‘!’ precedes the pipeline, the exit status is the logical negation of the exit status as described above. The shell waits for all commands in the pipeline to terminate before returning a value.
Then we have the info about 4.3.1 The set
Builtin:
-e
Exit immediately if a pipeline (see Pipelines), which may consist of a single simple command (see Simple Commands), a list (see Lists), or a compound command (see Compound Commands) returns a non-zero status. The shell does not exit if the command that fails is part of the command list immediately following a while or until keyword, part of the test in an if statement, part of any command executed in a && or || list except the command following the final && or ||, any command in a pipeline but the last, or if the command’s return status is being inverted with !.
All together, and quoting my own answer:
When you have:
set -e ! command1 command2
What you are doing is to by-pass the
set -e
flag in thecommand1
. Why?
- if
command1
runs properly, it will return a zero status.!
will negate it, butset -e
won't trigger an exit by the because it comes from a return status inverted with !, as described above.- if
command1
fails, it will return a non-zero status.!
will negate it, so the line will end up returning a zero status and the script will continue normally.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With