Bash doesn't seem to pass the "exit on error" environment flag into command substitution shells.
I am using a large number of command substitutions (to get around bash's lack of return values), but I'd still like the whole script to go down if something in the subshell fails.
So, for example:
set -e
function do_internet {
curl not.valid.address
}
answer=$(do_internet)
I'd like the script to stop there and then, and not continue. (I hoped that setting -e would stop from having to put '|| die' on everything.
Am I doing something wrong; and/or is there any way around this?
Here's a little example:
#!/bin/bash
set -e
echo "You should only see this line, and not any other line."
function foo {
false
echo "The above line is false. Figure that one out, Plato."
}
bar=$(foo)
echo $bar
It prints both lines.
(Using GNU bash, version 4.2.25(1)-release (x86_64-pc-linux-gnu)
)
For explanation I would say: set statement can also be used for command substitution. There can be a problem especially when the output of the command begins with a-. It may happen that set interprets it as an option. To avoid this condition, we have to use — (double hyphen) immediately after set.
One of the many known methods to exit a bash script while writing is the simple shortcut key, i.e., “Ctrl+X”. While at run time, you can exit the code using “Ctrl+Z”.
Exit When Any Command Fails This can actually be done with a single line using the set builtin command with the -e option. Putting this at the top of a bash script will cause the script to exit if any commands return a non-zero exit code.
An example with date : The command substitution syntax is $() . The command itself is date . Combining both we get $(date) , its value is the result of the substitution (that we could get after execution). We save that value in a variable, $thedate , for later use.
There is a difference in handling of -e
between subshells created with (...)
, as in Why doesn't bash flag -e exit when a subshell fails?, and subshells created with command substitution $(...)
, as in the OP.
According to the section COMMAND EXECUTION ENVIRONMENT
in the bash manual (and slightly confusingly):
Subshells spawned to execute command substitutions inherit the value of the -e option from the parent shell. When not in posix mode, bash clears the -e option in such subshells.
Regardless of the posix setting, the -e
only applies to the subshell created for the purposes of command substitution. So:
$ set -e
# The subshell has -e cleared
$ echo $(false; echo foo)
foo
$ set -o posix
# Now the subshell has -e, so it terminates at `false`
$ echo $(false; echo foo)
$
Nonetheless, -e
does apply to the execution of a command which only sets a variable. So
set -e
a=$(false)
will terminate the shell.
However, -e
does not apply to individual commands in a function. In the case of
fail() {
false
echo "failed"
}
The return value of fail
is 0 (i.e. success) because the echo
(which was the last command executed) succeeded. Consequently
a=$(fail) && echo ok
will set a
to failed
and then print ok
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