The set -e command makes a bash script fail immediately when any command returns an non-zero exit code.

  1. Is there an easy and elegant way to disable this behaviour for an individual command within a script?

  2. At which places is this functionality documented in the Bash Reference Manual ()?

7 Answers

  1. Something like this:

    #!/usr/bin/env bash set -e echo hi # disable exitting on error temporarily set +e aoeuidhtn echo next line # bring it back set -e ao echo next line 

    Run:

    $ ./test.sh hi ./test.sh: line 7: aoeuidhtn: command not found next line ./test.sh: line 11: ao: command not found 
  2. It's described in set builtin help:

    $ type set set is a shell builtin $ help set (...) Using + rather than - causes these flags to be turned off. 

The same is documented here: .

1

An alternative to unsetting the bail on error would be to force a success no matter what. You can do something like this:

cmd_to_run || true 

That will return 0 (true), so the set -e shouldn't be triggered

2

If you are trying to catch the return/error code (function or fork), this works:

function xyz { return 2 } xyz && RC=$? || RC=$? 
1

If the the "exit immediately shell option" applies or is ignored depends on the context of the executed command (see Bash Reference Manual section on the Set Builtin - thanks to Arkadiusz Drabczyk).

Especially, the option is ignored if a command is part of the test in an if statement. Therefore it is possible to execute a command and check for its success or failure within an "exit immediately context" using an if statement like this:

#!/bin/bash set -e # Uncomment next line to see set -e effect: #blubb if blubb; then echo "Command blubb was succesful." else echo "Command blubb failed. Exit code: $?" fi echo "Script exited normally." 

It is possible to omit the "then" statement and use fewer lines:

if blubb; then :; else echo "Command blubb failed. Exit code: $?"; fi 
1

Another approach, which I find fairly straightforward (and applies to other set options in addition to -e):

Make use of $- to restore settings.

For example:

oldopt=$- set +e # now '-e' is definitely disabled. # do some stuff... # Restore things back to how they were set -$oldopt 

Though for -e specifically, the options others have mentined (|| true or "put inside an if") may be more idiomatic.

I actually had a similar question recently (though I didn't post, I got around to it), and, from what I can see, it seems like just using set +e before the command and set -e afterward works most elegantly. Here's an example, grabbing the response of the command and not letting the error throw it away.

#!/bin/sh args="" for argcol in $* do args="${args} ${argcol}" done fortunevar="" fortfail="" { set +e fortunevar=`fortune $args` fortfail=$? set -e } &> /dev/null if [ $fortfail == 0 ] then echo ${fortunevar} say ${fortunevar} else echo misfortune: an illegal option was detected! echo misfortune: usage: misfortune [-afilosw] [-m pattern][ [#%] file/directory/all] fi 

This grabs the output of 'fortune', checking its exit status, and echoes and says it. I think this is what you were asking for, or at least something similar? Anyway, hope this helps.

1

I like to start subshell if want to change something temporarily. Below command demonstrates that first bad_command is ignored and second aborts execution.

bash -c 'set -e ;\ ( set +e; bad_command ; echo still here ) ;\ echo even here ; \ bad_command ; \ echo but not here;' 

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy