Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

What is the difference between the following methods of chaining commands?

cmd1; cmd2
cmd1 && cmd2
share|improve this question
I hate when I have to choose between two good answers :-) – varesa Apr 22 '12 at 19:28
up vote 94 down vote accepted

Assume there are command1 && command2. command2 will be executed if and only if command1 returned zero exit status.

; is just a command separator.

$> [[ "a" = "b" ]] && echo ok 

$> [[ "a" = "b" ]]; echo ok 
share|improve this answer
Similarly, command1 || command2 can be used to run command2 only if command1 returned a nonzero exit status. – hammar Apr 22 '12 at 20:19
Note that the return value of the full expression is the return value of the last command that was executed. – Stéphane Gimenez Apr 22 '12 at 22:05
Weird actually.. if command1 returns zero, then command2 is executed? Thinking about lazy evaluation, an && should not even look at the second argument when the first is already 0 - the result will be 0 anyway. – Konerak Apr 24 '12 at 8:57
@Konerak: With exit codes, 0 indicates success, or true while anything else is false, so it's sort of reversed compared to "ordinary" booleans. – hammar Apr 27 '12 at 20:25

cmd1; cmd2 executes cmd1, then cmd2, no matter what. It it exactly equivalent to putting cmd1 and cmd2 on separate lines. The return status of this compound command is that of cmd2.

cmd1 && cmd2 executes cmd1. Then, if the exit status of cmd1 is zero, cmd2 is executed. The return status of this compound command is that of cmd1 if it is nonzero (so cmd2 didn't run), and that of cmd2 otherwise (if it ran).

if cmd1; then cmd2; fi is mostly equivalent to cmd1 && cmd2. The main difference is that the version with if returns 0 if cmd1 returns a nonzero status.

A command returns 0 to indicate success, and a nonzero error code (between 1 and 255, usually between 1 and 125 as higher values have other meanings) to indicate failure. Thus cmd1; cmd2 means “execute these commands in sequence no matter what”, whereas cmd1 && cmd2 means “execute these commands, but stop immediately if the first command fails”.

You can tell the shell to enter “exit on error” mode by running set -e. In this mode, the shell exits as soon as any command returns a nonzero status, except in conditional constructs (the left side of && or ||, the condition part of if and while). Thus, under set -e, ; (or a newline) is effectively equivalent to &&¹.

¹ This isn't to say you can blindly replace && by ; if you've added set -e. For example, ; has lower precedence than &&, so cmd1 && cmd2 || cmd3 is equivalent to set -e; { cmd1; cmd2; } || cmd3. Also, set -e interacts badly with subshells — the details would derail this answer too far.

share|improve this answer
"as higher values have other meanings" what do they mean? If I'm writing my own program, is there any standard error naming (numbering?) convention? – rahmu Apr 23 '12 at 9:42
@rahmu Shells use error codes 126 and 127 to indicate that the program could not be started at all, and 128+N to indicate that the program died with signal N. So from a shell, the only status codes that unambiguously show that the program ran to completion are 0 to 126 (and 128, if you really want to confuse readers). – Gilles Apr 23 '12 at 17:02
@Gilles: I don't fully agree with the last sentence. Try echo $(set -e; { false; (exit 2) } && true; echo $?) vs echo $(set -e; { false && (exit 2) } && true; echo $?) ;) – Stéphane Gimenez Apr 23 '12 at 18:59
@StéphaneGimenez Ok, yes, set -e and subshells together can be funky. – Gilles Apr 23 '12 at 20:02

The first line will execute one command after another, irrespective of whether the first one succeeded or not. The second line is an example of shell logic: it will only execute the second command if the first one succeeded. This is because && is logical and. Therefore, if the first command fails, the logical state of the entire line is known to be false and there is no need to evaluate the second command.

share|improve this answer

More practical, there's a difference between

cd /backup/old; rm * -rf


cd /backup/old && rm * -rf

. Besides it's a stupid way, the first one will remove your whole filesystem (or $HOME, depending how it's called) because it runs rm regardless wherever the cd succeeded or not.

share|improve this answer
While your answer is correct, it's dangerous if a user ran it to see the difference for himself. Why not "echo something" instead? – Randy Stegbauer Apr 23 '12 at 17:46
I trust people not to do obviously stupid things. This is a +/- example I heard first hand. – Reactormonk Apr 23 '12 at 22:56
@RandyStegbauer Because people who will run this do not deserve to have files in their filesystem. – alexg Oct 15 '14 at 8:59

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.