First of all I\'m not a Bash pro. I discovered few months ago that if I use both the &&
and ||
short circuit operators in sequence with cur
Mr. Llama already corectly answered the question, this only for a quick reference what happens for different "combinations". The cmd0
is an "command" with zero-exit status and the cmd1
is with nonzero.
cmd0() { echo -n "[$@-0]"; return 0; }
cmd1() { echo -n "[$@-1]"; return 1; }
second() { echo "[second]"; }
doit() { echo "case: $@"; eval "$@"; echo; }
doit 'cmd0 start && cmd0 first && second'
doit 'cmd0 start && cmd0 first || second'
doit 'cmd0 start || cmd0 first && second'
doit 'cmd0 start || cmd0 first || second'
doit 'cmd0 start && cmd1 first && second'
doit 'cmd0 start && cmd1 first || second'
doit 'cmd0 start || cmd1 first && second'
doit 'cmd0 start || cmd1 first || second'
doit 'cmd1 start && cmd0 first && second'
doit 'cmd1 start && cmd0 first || second'
doit 'cmd1 start || cmd0 first && second'
doit 'cmd1 start || cmd0 first || second'
doit 'cmd1 start && cmd1 first && second'
doit 'cmd1 start && cmd1 first || second'
doit 'cmd1 start || cmd1 first && second'
doit 'cmd1 start || cmd1 first || second'
produces:
case: cmd0 start && cmd0 first && second
[start-0][first-0][second]
case: cmd0 start && cmd0 first || second
[start-0][first-0]
case: cmd0 start || cmd0 first && second
[start-0][second]
case: cmd0 start || cmd0 first || second
[start-0]
case: cmd0 start && cmd1 first && second
[start-0][first-1]
case: cmd0 start && cmd1 first || second
[start-0][first-1][second]
case: cmd0 start || cmd1 first && second
[start-0][second]
case: cmd0 start || cmd1 first || second
[start-0]
case: cmd1 start && cmd0 first && second
[start-1]
case: cmd1 start && cmd0 first || second
[start-1][second]
case: cmd1 start || cmd0 first && second
[start-1][first-0][second]
case: cmd1 start || cmd0 first || second
[start-1][first-0]
case: cmd1 start && cmd1 first && second
[start-1]
case: cmd1 start && cmd1 first || second
[start-1][second]
case: cmd1 start || cmd1 first && second
[start-1][first-1]
case: cmd1 start || cmd1 first || second
[start-1][first-1][second]
This is actually a very common Bash pitfall. It is not a bug.
returnNumber 0
evaluates to true, so the second block (joined by logical and &&
) is evaluated as well to make sure the result of first && second
is still true.
The second block outputs OK
but evaluates to false, so now the result of first && second
is false. This means that the third portion (joined by logical or ||
) must be evaluated as well, causing NG
to be displayed as well.
Instead of relying on &&
and ||
, you should be using if
statements:
if returnNumber 0; then
echo 'OK'
returnNumber 1
else
echo 'NG'
fi
tl;dr: Never use x && y || z
when y
can return a non-zero exit status.