The set -e command makes a bash script fail immediately when any command returns an non-zero exit code.
Is there an easy and elegant way to disable this behaviour for an individual command within a script?
At which places is this functionality documented in the Bash Reference Manual ()?
7 Answers
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 lineRun:
$ ./test.sh hi ./test.sh: line 7: aoeuidhtn: command not found next line ./test.sh: line 11: ao: command not foundIt's described in
setbuiltin 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: .
1An 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 || trueThat will return 0 (true), so the set -e shouldn't be triggered
2If 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 -$oldoptThough 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]
fiThis 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.
1I 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;'