Search code examples
bashexit-codeternary

Can I examine exit code within ternary operator?


I am trying to print a string depending on the exit code of a test built-in and ternary operator. I am successful to:

b=5
echo $(( b==5 ? good : bad ))   # good is printed

good is printed as expected, but if I do:

echo $(( test $b -eq 50 ? 123 : 321 ))
test 5 -eq 50 ? 123 : 321 : syntax error in expression (error token is "5 -eq 50 ? 123 : 321 ")
echo $(( $(test $b -eq 5)==0 ? 123 : 321 ))
 ==0 ? 123 : 321 : syntax error: operand expected (error token is "==0 ? 123 : 321 ")

Let's say I want to report file existence, none of the following didn't work as well:

echo $(( $((test -e file))==0 ? 123 : 321 ))
test -e file: syntax error in expression (error token is "file")
echo $(( ((test -e file))==0 ? 123 : 321 ))
((test -e file))==0 ? 123 : 321 : missing `)' (error token is "file))==0 ? 123 : 321 ")
echo $(( (test -e file)==0 ? 123 : 321 ))
(test -e file)==0 ? 123 : 321 : missing `)' (error token is "file)==0 ? 123 : 321 ")
echo $(( "test -e file" ? 123 : 321 ))
"test -e file" ? 123 : 321 : syntax error: operand expected (error token is ""test -e file" ? 123 : 321 ")

Is it any possible construct in ternary operator that can examine an exit code?


Solution

  • The $(( arithmetic context )) expects an arithmetic expression; obviously random strings (which apparently you hope to have executed as commands) are not arithmetic expressions, so that's a syntax error.

    Probably try

    echo $(( $(test "$b" -eq 50; echo $?) ? 123 : 321 ))
    

    etc; but obviously, a much less convoluted and more idiomatic way to say this is

    test "$b" -eq 50 && echo 123 || echo 321
    

    You can't refactor the echo out; in this isolated example, that's just a minor inconvenience. If you really need to avoid repeating more complex code, replace echo with a function which encapsulates whatever it is that you don't want to repeat.

    A $(command substitution) replaces the command with whatever it prints to standard output. If you want to examine its exit code, you need it to print that (and nothing else) to standard output, or use a different construction.