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 on command'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.