Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

Consider the following code

outer-scope.sh

#!/bin/bash
set -e
source inner-scope.sh
echo $(inner)
echo "I thought I would've died :("

inner-scope.sh

#!/bin/bash
function inner() { echo "winner"; return 1; }

I'm trying to get outer-scope.sh to exit when a call to inner() fails. Since $() invokes a sub-shell, this doesn't happen.

How else do I get the output of a function while preserving the fact that the function may exit with a non-zero exit code?

share|improve this question

2 Answers 2

up vote 10 down vote accepted

$() preserves the exit status; you just have to use it in a statement that has no status of its own, such as an assignment.

output=$(inner)

After this, $? would contain the exit status of inner, and you can use all sorts of checks for it:

output=$(inner) || exit $?
echo $output

Or:

if ! output=$(inner); then
    exit $?
fi
echo $output

Or:

if output=$(inner); then
    echo $output
else
    exit $?
fi

(Note: A bare exit without arguments is equivalent to exit $? – that is, it exits with the last command's exit status. I used the second form only for clarity.)


Also, for the record: source is completely unrelated in this case. You can just define inner() in the outer-scope.sh file, with the same results.

share|improve this answer
    
Why is it that, even though $? contains the exit status of $() that the script does not exit automatically (given that -e is set)? EDIT: nevermind, I think you have answered my questions, thanks! –  jabalsad Dec 2 '11 at 16:12
    
I'm not sure. (I haven't tested any of the above.) But there are some restrictions on -e, all explained in bash's manpage; also, if you are asking about echo $(), then it might be because the subshells' exit codes are ignored when the line - the echo command - has an exit code (usually 0) of its own. –  grawity Dec 2 '11 at 18:10
#!/bin/bash
set -e
source inner-scope.sh
foo=$(inner)
echo $foo
echo "I thought I would've died :("

By adding echo, the subshell does not stand alone (is not separately checked) and does not abort. Assignment circumvents this problem.

You can also do this, and redirect the output to a file, to later process it.

tmpfile=$( mktemp )
inner > $tmpfile
cat $tmpfile
rm $tmpfile
share|improve this answer
    
Of course, the $tmpfile continues to exist in the second variant... –  Daniel Beck Dec 1 '11 at 13:43

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.