I am confused about what error code the command will return when executing a variable assignment plainly and with command substitution:
a=$(false); echo $?
It outputs 1
, which let me think that variable assignment doesn't sweep or produce new error code upon the last one. But when I tried this:
false; a=""; echo $?
It outputs 0
, obviously this is what a=""
returns and it override 1
returned by false
.
I want to know why this happens, is there any particularity in variable assignment that differs from other normal commands? Or just be cause a=$(false)
is considered to be a single command and only command substitution part make sense?
-- UPDATE --
Thanks everyone, from the answers and comments I got the point "When you assign a variable using command substitution, the exit status is the status of the command." (by @Barmar), this explanation is excellently clear and easy to understand, but speak doesn't precise enough for programmers, I want to see the reference of this point from authorities such as TLDP or GNU man page, please help me find it out, thanks again!
I came across the same problem yesterday (Aug 29 2018).
In addition to
local
mentioned in Nick P.'s answer and @sevko's comment in the accepted answer,declare
in global scope also has the same behavior.Here's my Bash code:
The output:
Note the values of
local_ret2
andglobal_ret2
in the output above. The exit codes are overwritten bylocal
anddeclare
.My Bash version:
Upon executing a command as
$(command)
allows the output of the command to replace itself.When you say:
the output produced by the command
false
is stored in the variablea
. Moreover, the exit code is the same as produced by the command.help false
would tell:On the other hand, saying:
causes the exit code for the assignment to
a
to be returned which is0
.EDIT:
Quoting from the manual:
Quoting from BASHFAQ/002:
Note that this isn't the case when using
local
within a function. Which is subtly different behavior than described in the the accepted answer, and the posted link here: http://mywiki.wooledge.org/BashFAQ/002Take this bash script for example:
Here is the output of this:
Maybe nobody cares, but I did. It took me a minute to figure out why my status code was always 0 when it clearly wasn't sometimes. Not 100% clear why. But just knowing this helped.
(not an answer to original question but too long for comment)
Note that
export A=$(false); echo $?
outputs 0! Apparently the rules quoted in devnull's answer no longer apply. To add a bit of context to that quote (emphasis mine):IIUC the manual describes
var=foo
as special case ofvar=foo command...
syntax (pretty confusing!). The "exit status of the last command substitution" rule only applies to the no-command case.While it's tempting to think of
export var=foo
as a "modified assignment syntax", it isn't —export
is a builtin command (that just happens to take assignment-like args).=> If you want to export a var AND capture command substitution status, do it in 2 stages:
This way also works in
set -e
mode — exits immediately if the command substitution return non-0.