How can I call a Bash function without invoking command substitution?

729 views Asked by At

I have a Bash function that has a Perl-style "or die". For example,

#!/bin/bash
func1 () {
    local val
    val=`cat foobar` || exit 7
    echo "func1: cat returns $?"
}

myval=`func1`
echo "Line X should not be reached (retn = $? val = $myval)"
myval=$(func1)
echo "Line Y should not be reached (retn = $? val = $myval)"
func1
echo "Line Z should not be reached (retn = $?)"

Invoking function directly let's me leverage the exit. But if the function returns a value that I want to use, command substitution does not work with the exit. That is, the exit is just stored in the return value $? and the next line is executed.

Running with debug option -x seems to imply that command substitution is similar to subshell since bash outputs a deeper nesting for it. As such, the exit does not apply to the main script.

Sample output:

cat: foobar: No such file or directory
Line X should not be reached (retn = 7 val = )
cat: foobar: No such file or directory
Line Y should not be reached (retn = 7 val = )
cat: foobar: No such file or directory

Is there a way to invoke func1 and use its output (in a variable, loop, if, etc.) while still leveraging the short-circuit exit?

1

There are 1 answers

0
drvtiny On

You may use this simple code with SIGHUP signal handler included, it works perfectly as you wish :)

hndlHUP () {
    exit 7
}
func1 () {
    local val
    val=$(cat foobar) || kill -SIGHUP $$
    echo "func1: cat returns $?"
}

trap hndlHUP SIGHUP

myval=`func1`
echo "Line X should not be reached (retn = $? val = $myval)"
myval=$(func1)
echo "Line Y should not be reached (retn = $? val = $myval)"
func1
echo "Line Z should not be reached (retn = $?)"