Bash get exit status of command when 'set -e' is active?

Bash

Bash Problem Overview


I generally have -e set in my Bash scripts, but occasionally I would like to run a command and get the return value.

Without doing the set +e; some-command; res=$?; set -e dance, how can I do that?

Bash Solutions


Solution 1 - Bash

From the bash manual:

> The shell does not exit if the command that fails is [...] part of any command executed in a && or || list [...].

So, just do:

#!/bin/bash

set -eu

foo() {
  # exit code will be 0, 1, or 2
  return $(( RANDOM % 3 ))
}

ret=0
foo || ret=$?
echo "foo() exited with: $ret"

Example runs:

$ ./foo.sh
foo() exited with: 1
$ ./foo.sh
foo() exited with: 0
$ ./foo.sh
foo() exited with: 2

This is the canonical way of doing it.

Solution 2 - Bash

as an alternative

ans=0
some-command || ans=$?

Solution 3 - Bash

Maybe try running the commands in question in a subshell, like this?

res=$(some-command > /dev/null; echo $?)

Solution 4 - Bash

Given behavior of shell described at this question it's possible to use following construct:

#!/bin/sh

set -e

{ custom_command; rc=$?; } || :

echo $rc

Solution 5 - Bash

Use a wrapper function to execute your commands:

function __e {
    set +e
    "$@"
    __r=$?
    set -e
}

__e yourcommand arg1 arg2

And use $__r instead of $?:

if [[ __r -eq 0 ]]; then
    echo "success"
else
    echo "failed"
fi

Another method to call commands in a pipe, only that you have to quote the pipe. This does a safe eval.

function __p {
	set +e
	local __A=() __I
	for (( __I = 1; __I <= $#; ++__I )); do
		if [[ "${!__I}" == '|' ]]; then
			__A+=('|')
		else
			__A+=("\"\$$__I\"")
		fi
	done
	eval "${__A[@]}"
	__r=$?
	set -e
}

Example:

__p echo abc '|' grep abc

And I actually prefer this syntax:

__p echo abc :: grep abc

Which I could do with

...
		if [[ ${!__I} == '::' ]]; then
...

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDavid WoleverView Question on Stackoverflow
Solution 1 - BashAdrian FrühwirthView Answer on Stackoverflow
Solution 2 - BashKitsuneYMGView Answer on Stackoverflow
Solution 3 - BashPhil MillerView Answer on Stackoverflow
Solution 4 - BashreddotView Answer on Stackoverflow
Solution 5 - BashkonsoleboxView Answer on Stackoverflow