7

I have come across some strange behavious (well probably not strange but I don't understand it !)

I want to write some if / e,se statements using the bash shorthand syntax:

[[ 1 -eq 1 ]] && echo "true" || echo "false"

The output of the above code gives:

true

Now the code above actually works fine. But this next code does not:

[[ 1 -eq 1 ]] && infMsg "true" || infMsg "false"

infMsg is just a function. The output from the above code gives:

true
false

I only want it to say 'true'.

Is there something I am missing in the way the && || syntax handles exit codes from functions ?

ilium007
  • 539
  • 3
  • 8
  • 17

1 Answers1

16

I suspect your exit code for 'infMsg' is not 0 (success). If we break down the first piece of code:

[[ 1 -eq 1 ]] && echo "true" || echo "false"

What's happening is:

  • The [[ 1 -eq 1 ]] && echo "true" portion of code is evaluated first since && has a higher precedence than || (more info[here1)
  • The first half of that returns true. Then, since the first half was true, the second half executes the echo "true" statement. (&& -> If part one is true, run the second part)
  • Now we have the || echo "false". This part actually doesn't get executed since the first half (echo "true") returned true since the echo printed successfully ((||-> If part one is false, run the second part).).

Now if we break down the second piece of code:

[[ 1 -eq 1 ]] && infMsg "true" || infMsg "false"

What's most likely happening is:

  • [[ 1 -eq 1 ]] && infMsg "true" is evaluated. The first side is true. Then, since the first half was true, the second half executes the infMsg "true" statement. (&& -> If part one is true, run the second part).
  • Now we have || infMsg "false". If the infMsg "true" from the previous command didn't return a status code that is interpreted as success (0), the first half is interpreted as false, triggering the infMsg "false"((||-> If part one is false, run the second part).)..

The important info to pull away here:

  • || only runs the second half if the first half is FALSE.
  • && only run the second half if the first half is TRUE.
Paul Calabro
  • 1,748
  • 1
  • 16
  • 33
  • ok cool - thanks. I will check the ingMsg function and make sure it is explicitly returning an error code. – ilium007 Mar 21 '13 at 08:11
  • I did some testing and wrote a new infMsg function with **no** return code and it still worked as I expected. I thought that if a function exited with no explicit return it returns 0 if there were no internal errors. So I am still confused: `infMsg (){ echo -e "**$1" }` `[[ 1 -eq 1 ]] && infMsg "Test success" || infMsg "Test FAIL"` Still gives me: `**Test success` – ilium007 Mar 21 '13 at 09:40
  • 1
    Without an explicit `return` command, the exit status of a function is the exit status of the last command executed in the function. In this case, it's the exit status of `echo -e "**$1"`, which is (always?) 0. – chepner Mar 21 '13 at 12:50
  • 1
    A warning not to use this construct: https://github.com/koalaman/shellcheck/wiki/SC2015 – mgutt Dec 21 '21 at 08:23