Exit Code of Variable Assignment to Command Substitution in Bash

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

Exit code of command substitution in bash local variable assignment

If you look at the man file for local (which is actually just the BASH builtins man page), it is treated as its own command, which gives an exit code of 0 upon successfully creating the local variable. So local is overwriting the last-executed error code.

Try this:

function testing { local test; test="$(return 1)"; echo $?; }; testing

EDIT: I went ahead and tried it for you, and it works.

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

Local variable assignment with command substitution behaves unexpectedly

Not only local, all declaration utilities mask the exit code of the substituted command, because the assignment does not fail.

The usual workaround is:

local _ui_envname
_ui_envname=$(dialog --stdout --cancel-label "Back" --inputbox 'Enter the new environment name:' 0 0) || { echo "Failed"; exit 1; }

Will variable be assigned to empty if the command for command substitution failed in shell scriping?

No, it's not because the command failed that a is empty.

The command didn't produce any output data, so there is no data to be captured in a.

Revise the function to read:

f(){ echo Hello; return 1; }

Now run the command substitution. You'll find that a contains Hello. If you check $? immediately after the assignment, it contains 1, the status returned from the function. Exit statuses and command outputs are separate.

The documentation is in the GNU Bash manual for Command Substitution.

Can the exit code of a subshell be captured when declaring a variable with process substitution?

To check the status of the process substitution, the assignment must be the only thing performed by the statement. In a statement such as local x=$(false), the value returned is the status of local, which typically succeeds. To create a local readonly variable in a function and check the assignment from a process substitution, you can do:

local x
x=$(false) || echo "assigment of x failed !!" >&2
readonly x

getting the error code of a sub-command using $(...)

Use process substitution instead of command substitution + here string:

read X < <(grep 'hello' hello.txt)

This will get you 1 when using echo $?.

PS: If grep fails it will write an error on your terminal.

If you want to suppress error then use:

read X < <(grep 'hello' hello.txt 2>/dev/null)

Command Substitution does not execute unless i echo it

As GordonDavisson pointed out, removing the return statement and just printing it as an array did the job.

The function will return the printed value and i can parse that in the main program.



Related Topics



Leave a reply



Submit