They seem to both signal BASH to commence with another command following the symbols but is there a distinct difference?
6 Answers
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.
You can try the difference for yourself:
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.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.
- 768
&& is AND, meaning that the second command will only execute if the first one returned true (no errors).
- 3,912
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
- 25,251
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.
- 16,533