See the following examples and their outputs in POSIX shells:
false;echo $?
orfalse || echo 1
:1
false;foo="bar";echo $?
orfoo="bar" && echo 0
:0
foo=$(false);echo $?
orfoo=$(false) || echo 1
:1
foo=$(true);echo $?
orfoo=$(true) && echo 0
:0
As mentioned by the highest-voted answer at https://stackoverflow.com/questions/6834487/what-is-the-variable-in-shell-scripting:
$?
is used to find the return value of the last executed command.
This is probably a bit misleading in this case, so let's get the POSIX definition which is also quoted in a post from that thread:
? Expands to the decimal exit status of the most recent pipeline (see Pipelines).
So it appears as if a assignment itself counts as a command (or rather a pipeline part) with a zero exit value but which applies before the right side of the assignment (e.g. the command substitution calls in my examples here).
I see how this behavior makes sense from a practical standpoint but it seems somewhat unusual to me that the assignment itself would count in that order. Maybe to make more clear why it's strange to me, let's assume the assignment was a function:
ASSIGNMENT( VARIABLE, VALUE )
then foo="bar"
would be
ASSIGNMENT( "foo", "bar" )
and foo=$(false)
would be something like
ASSIGNMENT( "foo", EXECUTE( "false" ) )
which would mean that EXECUTE
runs first and only afterwards ASSIGNMENT
is run but it's still the EXECUTE
status that matters here.
Am I correct in my assessment or am I misunderstanding/missing something? Are those the right reasons for me viewing this behavior as "strange"?
false;foo="bar";echo $?
always return 0 when the last real command that ran wasfalse
?" It's basically that assignments behave special when it comes to exit codes. Their exit code is always 0, except when it isn't because of something which ran as part of the right-hand side of the assignment. – phk Jan 29 '17 at 17:12