How to Disable Set -E for an Individual Command?
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...
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: .
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
If you are trying to catch the return/error code (function or fork), this works:
function xyz {
return 2
}
xyz && RC=$? || RC=$?
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
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.
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;'