Exit code of variable assignment to command substitution in Bash
Upon executing a command as $(command)
allows the output of the command to replace itself.
When you say:
a=$(false) # false fails; the output of false is stored in the variable a
the output produced by the command false
is stored in the variable a
. Moreover, the exit code is the same as produced by the command. help false
would tell:
false: false
Return an unsuccessful result.
Exit Status:
Always fails.
On the other hand, saying:
$ false # Exit code: 1
$ a="" # Exit code: 0
$ echo $? # Prints 0
causes the exit code for the assignment to a
to be returned which is 0
.
EDIT:
Quoting from the manual:
If one of the expansions contained a command substitution, the exit status of the command is the exit status of the last command substitution performed.
Quoting from BASHFAQ/002:
How can I store the return value and/or output of a command in a variable?
...
output=$(command)
status=$?
The assignment to
output
has no effect oncommand
's exit status, which is still in$?
.
Note that this isn't the case when combined with local
, as in local variable="$(command)"
. That form will exit successfully even if command
failed.
Take this Bash script for example:
#!/bin/bash
function funWithLocalAndAssignmentTogether() {
local output="$(echo "Doing some stuff.";exit 1)"
local exitCode=$?
echo "output: $output"
echo "exitCode: $exitCode"
}
function funWithLocalAndAssignmentSeparate() {
local output
output="$(echo "Doing some stuff.";exit 1)"
local exitCode=$?
echo "output: $output"
echo "exitCode: $exitCode"
}
funWithLocalAndAssignmentTogether
funWithLocalAndAssignmentSeparate
Here is the output of this:
nick.parry@nparry-laptop1:~$ ./tmp.sh
output: Doing some stuff.
exitCode: 0
output: Doing some stuff.
exitCode: 1
This is because local
is actually a builtin command, and a command like local variable="$(command)"
calls local
after substituting the output of command
. So you get the exit status from local
.