Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Exit code of variable assignment to command substitution in Bash

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!

like image 996
Reorx Avatar asked Nov 23 '13 02:11

Reorx


People also ask

What is exit code 2 in bash?

All of the Bash builtins return an exit status of zero if they succeed and a non-zero status on failure, so they may be used by the conditional and list constructs. All builtins return an exit status of 2 to indicate incorrect usage, generally invalid options or missing arguments.

How do I set an exit code in bash?

To set an exit code in a script use exit 0 where 0 is the number you want to return. In the following example a shell script exits with a 1 . This file is saved as exit.sh . Executing this script shows that the exit code is correctly set.

What does $() mean in bash?

The dollar sign before the thing in parenthesis usually refers to a variable. This means that this command is either passing an argument to that variable from a bash script or is getting the value of that variable for something.


2 Answers

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 $?.

like image 196
devnull Avatar answered Oct 14 '22 15:10

devnull


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.

like image 34
Nick P. Avatar answered Oct 14 '22 15:10

Nick P.