What is the proper way to test a Bash function's return value?

If it was the exit code and not the result, you could just use

if func arg; then ...

If you cannot make the function return a proper exit code (with return N), and you have to use string results, use Alex Gitelman's answer.

$ help if:

if: if COMMANDS; then COMMANDS; [ elif COMMANDS; then COMMANDS; ]... [ else COMMANDS; ] fi

Execute commands based on conditional.

The if COMMANDS list is executed. If its exit status is zero, then the then COMMANDS list is executed. Otherwise, each elif COMMANDS list is executed in turn, and if its exit status is zero, the corresponding then COMMANDS list is executed and the if command completes. Otherwise, the else COMMANDS list is executed, if present. The exit status of the entire construct is the exit status of the last command executed, or zero if no condition tested true.

Exit Status: Returns the status of the last command executed.


If you need to test two conditions, one being the exit status of function/command and the other e.g. value of variable, use this:

if func arg && [[ $foo -eq 1 ]]; then echo TRUE; else echo FALSE; fi

This error seems to be produced if the function returns more than one word.

For example, 1 2.

Just quote it:

"$(func arg)"

Sample:

$ if [[ 1 2 ]] ; then echo 1 ; fi
-bash: conditional binary operator expected
-bash: syntax error near `2'
$ if [[ "1 2" ]] ; then echo 1 ; fi
1

And if you compare 0 vs non 0, just use

if [[ "$(func arg)" != "0" ]]

On a related note, if the function returns a variety of exit codes instead of true/false, then:

func args; ec=$?      # call function and grab the exit code
                      # it is better to have them on the same line so that a future addition of a command
                      # before the case statement wouldn't break the logic
case $ec in
  value1) # commands
          ;;
  value2) # commands
          ;;
  *)      # commands
          ;;
esac