61

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

6 Answers 6

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.

1
  • 1
    Interesting! I had thought it might just be a more comfortable way. Thank you!
    – user6658
    Jan 27, 2011 at 17:38
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.

0
9

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

8
  • 1
    && is a "then" (not an "and")... see my answer
    – Peter.O
    Feb 9, 2011 at 6:34
  • 2
    @fred I'd say it's an "and" with short-circuit evaluation - if the first part is non-true it knows that the total result must be false, so it skips the second part. But agree that thinking of it as a "then" rarely makes much difference in this context. Feb 9, 2011 at 7:08
  • 2
    @fred Though conceptually it might be easier to understand it that way, I disagree with your statement. The idea is simply that with any AND execution the 2nd parameter becomes irrelevant if the first one equals false and so the underlying code gets optimized to postpone evaluation of the 2nd parameter till it knows what the first one is. Feb 11, 2011 at 15:20
  • 2
    @fred I'm not sure what point that example is trying to make. && is just a binary operator, a function. The only "special" thing is that it is infix notation (which is standard for most of these kind of operators anyway) and delayed execution of the second operand. That delayed execution indeed gives it the ability to be used as something that can be conceptually viewed as an if statement in this context, but that doesn't take away from the fact that it's originally intended usage is within the conditional of an actual if statement. The use here really is more of a "hack". Feb 11, 2011 at 22:34
  • 3
    @fred Of course it isn't a ternary operator, it just is the succession of two operations a && b || c = (a && b) || c. Simple order of evaluation. There's really no mystery there. If you would write them like your typical functions, it would simply look like or(and(a, b), c). This logic is the same within an if conditional as well as when entering it straight into the command line because && and || are operators, they take two operands and they return another. Feb 12, 2011 at 11:30
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 

0
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.

You must log in to answer this question.