61

They seem to both signal BASH to commence with another command following the symbols but is there a distinct difference?

6 Answers6

83

With this line:

command1 && command2

command2 will be executed if (and only if) command1 returns exit status zero, whereas in this line:

command1 ; command2

both command1 and command2 will be executed regardless. The semicolon allows you to type many commands on one line.

43

You can try the difference for yourself:

  1. ls /invalid/path && echo "hello!"
    since /invalid/path doesn't exist, ls can't show you the directory listing. It will fail with an error message: "ls: /invalid/path: No such file or directory".
    The second half of the command (echo "hello!") is never even executed because the first half failed.

  2. ls /invalid/path ; echo "hello!"
    The same error message appears as before, but this time, the second part is executed!
    ls: /invalid/path: No such file or directory
    hello!

Why is this useful?
Suppose you want to extract a file called archive.tar.gz
You could use the command tar zxvf archive.tar.gz && rm archive.tar.gz.
If for any reason the extraction of the archive fails, the second part isn't executed! You can try again.

If you use ; in the same situation, the archive is deleted and you can't try again.

9

&& is AND, meaning that the second command will only execute if the first one returned true (no errors).

8

Update: I've added as script to highight some of the possible traps:

Because no-one else has mentioned "||", I will

Update2: some important re-wording here
&& is like a "then" of an "if" statement which responds to "true"

|| is NOT like the "else" of an "if" statment..
|| is like a "then" of an "if" statement which responds to "false"

More specificaly, && tests the $? return value of the previous most recently executed statement and passes control to the statement or sub-shell immediately following the &&... it only passes control if $? is true.

|| is similar, and is often seen following a && statement, but it tests for a false return value ($?) from the previous most recently executed statement... NB!, Nota Bene! Note well!.... if the predecing statement is an && statement which retruns false when you expect it to be true, then || will respond to the false, so mixing both on the same line may be risky

The main point I am trying to make is in relation to a mistake I made. ie:
## [[condition]] && A || B
is not does not behave like a C/C++ style ternary. ie:
// (condition) ? A : B
See the script below for examples of "unexpected" results from "A"

The basic test and the && and the || statement must all be on the same line...


Run this script to see where things can go wrong when using && and ||
The most recently executed statement may not be the one you expect..

[[ condition]] && echo Hello || echo Goodbye .... is typically safe,
becaue a well formed echo will return true.
but what about accessing a file which doesnt exits?

#!/bin/bash
#
# "as expected" return codes" means: expected to behave like a normal AND / OR  contition test
#
if [[ "$1" != "" ]] ; then exit $1; fi # recursive call to return an arbitary $? value (decimal)
echo
echo 'test 1: All return codes are "as expected"'
echo  ======
 ((1==1)) && echo  " ((1==1)) rc=$? ..&&.. condition is true" || echo  " ((1==1)) rc=$? ..||.. condition is false"
  $0  0   && echo "  \$0  0   rc=$? ..&&.. condition is true" || echo "  \$0  0   rc=$? ..||.. condition is false"
 ((1!=1)) && echo  " ((1!=1)) rc=$? ..&&.. condition is true" || echo  " ((1!=1)) rc=$? ..||.. condition is false"
  $0  1   && echo "  \$0  1   rc=$? ..&&.. condition is true" || echo "  \$0  1   rc=$? ..||.. condition is false"
echo
echo 'test 2: Now throw in some "unexpected" errors into the first of the &&/|| pair' 
echo  ======
 ((1==1)) && (echo  " ((1==1)) rc=$? ..&&.. condition is true"; $0 1)  || echo  " ((1==1)) rc=$? ..||.. condition is false"
  $0  0   && (echo "  \$0  0   rc=$? ..&&.. condition is true"; $0 2)  || echo "  \$0  0   rc=$? ..||.. condition is false"
 ((1!=1)) && (echo  " ((1!=1)) rc=$? ..&&.. condition is true"; $0 3)  || echo  " ((1!=1)) rc=$? ..||.. condition is false"
  $0  1   && (echo "  \$0  1   rc=$? ..&&.. condition is true"; $0 4)  || echo "  \$0  1   rc=$? ..||.. condition is false"
echo
echo 'test 3: Now swap the order of && and || statements, using "as expected" return codes'
echo  ======
 ((1==1)) || echo  " ((1==1)) rc=$? ..||.. condition is true" && echo  " ((1==1)) rc=$? ..&&.. condition is false"
  $0  0   || echo "  \$0  0   rc=$? ..||.. condition is true" && echo "  \$0  0   rc=$? ..&&.. condition is false"
 ((1!=1)) || echo  " ((1!=1)) rc=$? ..||.. condition is true" && echo  " ((1!=1)) rc=$? ..&&.. condition is false"
  $0  1   || echo "  \$0  1   rc=$? ..||.. condition is true" && echo "  \$0  1   rc=$? ..&&.. condition is false"
echo
echo 'test 4: With the order of && and || statements still swapped, introduce "unexpected" errors into the first of the &&/|| pair' 
echo  ======
 ((1==1)) && (echo  " ((1==1)) rc=$? ..&&.. condition is true"; $0 1)  || echo  " ((1==1)) rc=$? ..||.. condition is false"
  $0  0   && (echo "  \$0  0   rc=$? ..&&.. condition is true"; $0 2)  || echo "  \$0  0   rc=$? ..||.. condition is false"
 ((1!=1)) && (echo  " ((1!=1)) rc=$? ..&&.. condition is true"; $0 3)  || echo  " ((1!=1)) rc=$? ..||.. condition is false"
  $0  1   && (echo "  \$0  1   rc=$? ..&&.. condition is true"; $0 4)  || echo "  \$0  1   rc=$? ..||.. condition is false"

exit 

Peter.O
  • 25,251
1

try

false && echo "hello"

and

false ; echo "hello"

see the difference

0

The command (function, in case of a script) after && is executed depending upon the RETVAL of the first command (function, in case of a script). It forces the first command to return a value of 0, if successful. We can check the return value to execute further commands.

theTuxRacer
  • 16,533