mpen
mpen

Reputation: 282875

How does && work in shell?

I'm using Bash specifically, but I imagine most shells behave the same way.

I often do

hg pull && hg update --clean

But it just occurred to me, if hg pull returns 0 on success, why does it execute the hg up command?

Typically the way the && operator works is that it will only execute the next argument if the previous one was truthy. Is 0 truthy in Bash, or what?

This came up because I tried doing the equivalent in Python, but I had to write it like this:

call(['hg','pull']) or call(['hg','update','--clean'])

Upvotes: 2

Views: 867

Answers (2)

clt60
clt60

Reputation: 63902

As help, you can remember than command when end correctly (without errors) mean true. And his exit codes are zero

so,

  • correct = OK = true = exit status 0
  • incorrect = BAD = false = exit status > 0

therefore, for example, the correct way deleting all files recursively is

$ pwd
/
$ cd /tnp && rm -rf *
cd: can't change directory  #and the rm WILL NOT executed

and not

$ pwd
/
$ cd /tnp ; rm -rf *
cd: can't change directory  #but the rm IS executed (in the root directory)

Added:

command1 && command2 && command3
               ^            ^
               |            +-- run, only when command2 exited OK (zero)
               |
               +--run only when command1 exited OK (zero) 

So, command3 will not executed if command1 or command2 failed. (when comman1 fails, the command2 will don't execued (fail) so command3 not executed too.

Play with the next

run() {
    echo "comand-$2($1)"
    return $1
}

ok() {
    run 0 $1
}
fail() {
    run 1 $1
}

echo "OK && OK && ANY"
ok A && ok B 0 && ok C
echo

echo "OK && FAIL && ANY"
ok A 0 && fail B 1 && ok C
echo

echo "FAIL && ANY && ANY"
fail A && ok B && ok C
echo

echo "OK || ANY || ANY"
ok A || ok B || ok C
echo

echo "FAIL || OK || ANY"
fail A || ok B || ok C
echo

echo "FAIL || FAIL || OK"
fail A || fail B || ok C
echo

echo "FAIL && OK || OK"
fail A && ok B || ok C
echo

the result

OK && OK && ANY
comand-A(0)
comand-B(0)
comand-C(0)

OK && FAIL && ANY
comand-A(0)
comand-B(1)

FAIL && ANY && ANY
comand-A(1)

OK || ANY || ANY
comand-A(0)

FAIL || OK || ANY
comand-A(1)
comand-B(0)

FAIL || FAIL || OK
comand-A(1)
comand-B(1)
comand-C(0)

FAIL && OK || OK
comand-A(1)
comand-C(0)

The last construction is neat, because you can write

command1 && (commands if the command1 is successful) || (commands if not)

Upvotes: 3

Christopher Neylan
Christopher Neylan

Reputation: 8272

The '&&' operator operates in two ways in Bash.

On one hand, it's a conditional operator as you'd expect:

if [ $condition1 ] && [ $condition2 ]
#  Same as:  if [ $condition1 -a $condition2 ]
#  Returns true if both condition1 and condition2 hold true...

if [[ $condition1 && $condition2 ]]    # Also works.
#  Note that && operator not permitted inside brackets
#+ of [ ... ] construct.

On the other hand, it can be used to concatenate commands, in which case it explicitly checks the return codes of the commands and proceeds down the chain when the value is 0. See the doc.

Upvotes: 2

Related Questions