Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do not abort script if a specific command fails

Tags:

bash

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
like image 873
blueFast Avatar asked Dec 05 '22 12:12

blueFast


2 Answers

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
like image 189
Inian Avatar answered Jan 09 '23 18:01

Inian


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 the command1. Why?

  • if command1 runs properly, it will return a zero status. ! will negate it, but set -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.
like image 34
fedorqui 'SO stop harming' Avatar answered Jan 09 '23 18:01

fedorqui 'SO stop harming'