48

When you want to run multiple commands you can use ;, && and |

Like this: killall Finder; killall SystemUIServer, cd ~/Desktop/ && rm Caches Or: man grep | man cat for example.

But, is there a difference between |, ; and &&? If so, what is the difference?

Pro Backup
  • 4,924
DisplayName
  • 11,688
  • 1
    Sorry, but have you tried man bash? – Martin Schröder Oct 06 '14 at 12:02
  • 9
    That man page is gigantic and can be daunting to someone new to bash. – Anthony Oct 06 '14 at 14:23
  • I agree with qweliun, its almost 40k words. Why say sorry? – DisplayName Oct 06 '14 at 14:27
  • 1
    It's trivial to find when searching, e.g. && is explained in the paragraph containing the second match. – Daniel Beck Oct 06 '14 at 16:10
  • 3
    No, this was asked 20 hours ago, his question was asked 16 hours ago. That question is a duplicate of mine. – DisplayName Oct 06 '14 at 18:53
  • @DisplayName when you asked your question yesterday, we realized that this information was fractured across various posts and we didn't have a nice canonical Q&A that explains all of the shell's operators. That's why I wrote one. Note that my answer deals with what you're asking but the answers you have here only deal with a subset of what the dupe is asking. – terdon Oct 06 '14 at 19:08
  • Ok, I'm sorry, i understand. – DisplayName Oct 06 '14 at 19:17
  • Closing as a duplicate of the earlier question is the common case. But there are other factors: if question A is more general but its answers still fully and adequately answer question B, the duplicate has to be the A, because answers to A don't fully cover B. This is the case here. Another case is if a newer question attracts better answers, then we keep open the one with the best answers. – Gilles 'SO- stop being evil' Oct 06 '14 at 19:25
  • @DisplayName I have posted a question on meta discussing this. Please post an answer if you are still uncomfortable with it. – terdon Oct 06 '14 at 19:39
  • 2
    Displayname - I think your question is the better of the two - it is not singly focused on bash as is the other. I also find it strange that a question with an answer garnering 34 votes - as @jimmij's has - should be so easily dismissed. I noted my own disapproval in this answer to terdon's meta question and - for what little it is likely to be worth - I have voted to reopen this question. – mikeserv Oct 06 '14 at 21:42

5 Answers5

120
  • ;: commands separated by a ; are executed sequentially. The shell waits for each command to terminate in turn.

  • &&: command after && is executed if, and only if, command before && returns an exit status of zero. You can think of it as AND operator.

  • |: a pipe. In expression command1 | command2 The standard output of command1 is connected via a pipe to the standard input of command2.

There are more similar control operators, worth to mention:

  • ||: command after || is executed if, and only if, command before || returns a non-zero exit status. You can think of it as OR operator. Please note, that | and || are completely different animals.

  • &: the shell executes the command terminated by & in the background, does not wait for the command to finish and immediately returns exit code 0. Once again, & has nothing to do with &&.

  • |&: a shorthand for 2>&1 | i.e. both standard output and standard error of command1 are connected to command2's standard input through the pipe.

Additionally if you use zsh then you can also start command with &| or &!. In this case job is immediately disowned, after startup it does not have a place in the job table.

jimmij
  • 47,140
  • 1
    You might as well add & since & and ; are similar, and your description of ; providing sequential execution provides a good segue into & providing non-sequentialized execution. – Nick Russo Oct 06 '14 at 00:24
  • You are right, I've added it and a few more. – jimmij Oct 06 '14 at 01:03
  • great answer, can you also list >, &> and >>? I see it a lot and I still don't get it – João Pimentel Ferreira Sep 06 '20 at 08:46
  • @JoãoPimentelFerreira The post is quite old. I don't know if the original creator still monitors it or not. But other than a few symbols left, it's gold. :-) – Hammad Ahmed Sep 02 '21 at 12:25
  • @HammadAhmed An answer at StackOverflow is intended for the whole world, not just the OP. – Ruan Mendes Oct 27 '21 at 20:30
  • I found this when I was trying to run multiple npm scripts concurrently and I picked & as my solution. Then I came to know that all the processes run in the background even I ctrl + c to exit. I had to manually find the process ids and kill them. So I decided to use concurrently npm package. So I think when you're using &, you should know it's consequences. – Imran Mar 15 '23 at 11:50
14

Consider two commands A and B. When you write

A | B

A and B are executed in parallel, and the standard output of A is sent as the standard input of B.

When you write

A; B

A is executed, then B is executed (unless set -e has been used and A terminates with a non-zero exit status, in which case the shell terminates just after A).

When you write

A && B

A is executed, then B is executed only if A has terminated successfully (zero exit status). This form can be safer than the previous one, e.g. with

cd some_dir && rm file*

The && makes sure that the right files are removed, i.e. files are removed only if the cd has succeeded.

vinc17
  • 12,174
7

The other answers already explain |, && and ;, so I'll add something additional you haven't explicitly asked for: ||.

A || B

A is executed, and then B is only executed if A failed. This is useful for reacting on error conditions:

martin@martin ~ % rm doesnotexist 2>/dev/null || echo "failed to delete file"
failed to delete file

(The 2>/dev/null is necessary to hide the error message of rm itself.)

4

All three are rather different from one-another, especially |.

  • |: First of all it's called a 'pipe', and can be used to redirect the output of one program into the other. Your example won't actually do anything meaningful tho because man doesn't use standard input for anything. A more meaningful example would be man grep | grep -- -v which will find '-v' in the output from man grep

  • ;: The semicolon can be used instead of a newline, to make things take up less space.

  • &&: The two ampersand operator is a boolean AND operator which means that the command after the && will be run if, and only if, the command on the left side returns true, which on UNIX systems means that it returned with the exit code 0.

remmy
  • 5,055
  • 1
  • 24
  • 30
2

No one seems to be explaining why you would use each one, given your actual examples. I'll take a stab at it:

killall Finder; killall SystemUIServer

A command like killall can take some time to execute. By using the semicolon, you can give both commands at once and then do something else while you wait. That way you don't have to wait twice (once for each command).

cd ~/Desktop/ && rm Caches

You want to remove the directory ~/Desktop/Caches and end up in the directory ~/Desktop. What you do not want to do is to remove the directory Caches from the current directory (before you change it). So you use && to check that the directory change was successful before you do your remove command.

man grep | man cat

This makes no sense to me. The man command does not process input, so piping things to it won't do anything. Perhaps you meant

man grep || man cat

That would try to find the man page for grep and then if it couldn't, would show the man page for cat. Or possibly you meant

man grep | cat

That would use cat to display the man page rather than the pager (normally less). The | redirects the output from man to the command cat (which just dumps everything to screen). This can be useful in a GUI where you can use the scroll bar to go back and forth in the file rather than using the keyboard commands in less.

Note: if you want to know what ; && | || do in the more general cases, then I'd suggest looking at jimmij's answer. I'm just trying to explain what's happening in the examples from the question.

HalosGhost
  • 4,790
Brythan
  • 123
  • The reason for the commands not making sense is because i just typed out something random, it was not meant to be effective. – DisplayName Oct 06 '14 at 07:48