471

As far as I know, using & after the command is for running it in the background.

Example of & usage: tar -czf file.tar.gz dirname &

But how about &&? (example)

Gulzar
  • 23,452
  • 27
  • 113
  • 201
Captain
  • 4,797
  • 4
  • 16
  • 6

10 Answers10

528

Furthermore, you also have || which is the logical or, and also ; which is just a separator which doesn't care what happend to the command before.

$ false || echo "Oops, fail"
Oops, fail

$ true || echo "Will not be printed"
$  

$ true && echo "Things went well"
Things went well

$ false && echo "Will not be printed"
$

$ false ; echo "This will always run"
This will always run

Some details about this can be found here Lists of Commands in the Bash Manual.

bsheps
  • 1,438
  • 1
  • 15
  • 26
plundra
  • 18,542
  • 3
  • 33
  • 27
  • 4
    There's also this "trick". `Command && echo "Command worked" || echo "Command Failed"` – Dan Jun 24 '20 at 00:49
  • 7
    @Dan That's a bad trick. It only works as expected if you can guarantee the command after `&&` will succeed. `if command; then command; else command; fi` is not significantly longer and will always work as expected. – chepner Oct 27 '21 at 14:17
490

&& lets you do something based on whether the previous command completed successfully - that's why you tend to see it chained as do_something && do_something_else_that_depended_on_something.

girasquid
  • 15,121
  • 2
  • 48
  • 58
165

command-line - what is the purpose of &&?

In shell, when you see

$ command one && command two

the intent is to execute the command that follows the && only if the first command is successful. This is idiomatic of Posix shells, and not only found in Bash.

It intends to prevent the running of the second process if the first fails.

You may notice I've used the word "intent" - that's for good reason. Not all programs have the same behavior, so for this to work, you need to understand what the program considers a "failure" and how it handles it by reading the documentation and, if necessary, the source code.

Your shell considers a return value of 0 for true, other positive numbers for false

Programs return a signal on exiting. They should return 0 if they exit successfully, or greater than zero if they do not. This allows a limited amount of communication between processes.

The && is referred to as AND_IF in the posix shell grammar, which is part of an and_or list of commands, which also include the || which is an OR_IF with similar semantics.

Grammar symbols, quoted from the documentation:

%token  AND_IF    OR_IF    DSEMI
/*      '&&'      '||'     ';;'    */

And the Grammar (also quoted from the documentation), which shows that any number of AND_IFs (&&) and/or OR_IFs (||) can be be strung together (as and_or is defined recursively):

and_or           :                         pipeline
                 | and_or AND_IF linebreak pipeline
                 | and_or OR_IF  linebreak pipeline

Both operators have equal precedence and are evaluated left to right (they are left associative). As the docs say:

An AND-OR list is a sequence of one or more pipelines separated by the operators "&&" and "||" .

A list is a sequence of one or more AND-OR lists separated by the operators ';' and '&' and optionally terminated by ';', '&', or .

The operators "&&" and "||" shall have equal precedence and shall be evaluated with left associativity. For example, both of the following commands write solely bar to standard output:

$ false && echo foo || echo bar
$ true || echo foo && echo bar
  1. In the first case, the false is a command that exits with the status of 1

    $ false
    $ echo $?
    1
    

    which means echo foo does not run (i.e., shortcircuiting echo foo). Then the command echo bar is executed.

  2. In the second case, true exits with a code of 0

    $ true
    $ echo $?
    0
    

    and therefore echo foo is not executed, then echo bar is executed.

Russia Must Remove Putin
  • 374,368
  • 89
  • 403
  • 331
33

A quite common usage for '&&' is compiling software with autotools. For example:

./configure --prefix=/usr && make && sudo make install

Basically if the configure succeeds, make is run to compile, and if that succeeds, make is run as root to install the program. I use this when I am mostly sure that things will work, and it allows me to do other important things like look at stackoverflow an not 'monitor' the progress.

Sometimes I get really carried away...

tar xf package.tar.gz && ( cd package; ./configure && make && sudo make install ) && rm package -rf

I do this when for example making a linux from scratch box.

Nigel Atkinson
  • 660
  • 6
  • 11
  • 2
    Good in REPL, but for scripts I would prefer `set -o errexit` for Bash. – Franklin Yu Feb 11 '17 at 11:38
  • note that `set -o errexit` (same as `set -e`) may not work as expected when using `&&`. See `man set`: in an "AND-OR list" it will ignore anything but the last command according to the manpage, so as I understand it, if you expect it to stop the entire script on the first failure in such a list, it will not. – pzkpfw Jul 16 '22 at 10:01
23

&& strings commands together. Successive commands only execute if preceding ones succeed.

Similarly, || will allow the successive command to execute if the preceding fails.

See Bash Shell Programming.

Dean Burge
  • 3,440
  • 25
  • 22
12

It's to execute a second statement if the first statement ends successfully. Like an if statement:

 if (1 == 1 && 2 == 2)
   echo "test;"

It first tries if 1==1. If that is true, it checks if 2==2.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Nick
  • 1,441
  • 11
  • 22
  • 1
    Could someone explain why this was downvoted for users stumbling upon the question? – ajspencer Aug 07 '17 at 19:49
  • 1
    @user3243242 it's not wrong, just a poor example to illustrate the usage of `&&` – dan Sep 29 '17 at 02:49
  • It' s a great insight into how `if` tests work in bash. I never thought of it like a chain of comparison commands, breaking when any of them failed. So you've got my upvote :) – PiRK Nov 24 '17 at 12:50
  • 1
    The consequence is that you can get the opposite behavior by using `||`, to chain commands until one of them succeeds: `eei || leu || uie || echo prout3 || echo "never executed"` – PiRK Nov 24 '17 at 12:55
8

See the example:

mkdir test && echo "Something" > test/file

The shell will try to create directory test and then, only if it was successful will try create file inside it.

So you may interrupt a sequence of steps if one of them failed.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
alno
  • 3,556
  • 1
  • 19
  • 10
7

command_1 && command_2: execute command_2 only when command_1 is executed successfully.

command_1 || command_2: execute command_2 only when command_1 is not successful executed.

Feels similar as how an 'if' condition is executed in a mainstream programming language, like, in if (condition_1 && condition_2){...} condition_2 will be omitted if condition_1 is false and in if (condition_1 || condition_2){...} condition_2 will be omitted if condition_1 is true. See, it's the same trick you use for coding :)

Xiaonin Li
  • 71
  • 1
  • 2
  • I don't know what you mean by 'exactly the opposite', but $echo '1' || echo '2' prints only '1'. and $wrong_command || echo '2' prints an error message and '2' on the next line. Could you explain a little more about what do you think is wrong about it? – Xiaonin Li Jun 30 '17 at 02:04
1
####################### && or (Logical AND) ######################
first_command="1"
two_command="2"

if [[ ($first_command == 1) && ($two_command == 2)]];then
 echo "Equal"
fi

When program checks if command, then the program creates a number called exit code, if both conditions are true, exit code is zero (0), otherwise, exit code is positive number. only when displaying Equal if exit code is produced zero (0) that means both conditions are true.

Amin
  • 11
  • 2
  • Welcome to stackoverflow. Please make sure your code snippet works before posting here. You have to correct it `if [[ ($first_command == "1") && ($two_command == "2") ]];then echo "Equal"; fi` – Zheng Qu Mar 03 '20 at 13:52
0

Thanks to all the above you helped me solve how to return the first line of files matching a grep (in my case the first line contains the URL of the file source)

for var in sources/* ; do grep -iw "keyword" $var && head -n 1 $_; done

Unfortunately I cannot work out how to do this without the for loop - which limits the scalability I think. I have about 1000 files.

Paul Walsh
  • 21
  • 4