Bash difference between |, &, || and &&
|
: It is the pipe operator. It passes the stdout of first command to the next command.
$ echo a | echo b | echo c
c
`&`: It starts a asynchronous process.
||
: It is like the boolean or operator. If the first half succeeds then don't executable the second half.
$ echo a || echo b
a
&&
: It is like the boolean and operator. Executable both halves.
&&
and ||
are straight forward. But |
&
executes the command as a separate script, only forwarding the stdout and stderr.
Examples:
echo a
executes and printsa
, with statuscode 0. Now since&&
isand
operator,echo b
is also executed but its output is not displayed on terminal. Its output is followed as stdin toecho c
which printsc
.
$ echo a && echo b | echo c
a
c
- asd is not a command and trying to execute it fails. Then
echo b
doesn't execute as&&
is and operator. Since,echo b
doesn't execute there is nothing to pass through|
pipe operator. Hence,echo c
doesn't execute.
$ asd && echo b | echo c
zsh: command not found: asd
- Executing
asd
fails and empty stdout ofasd
is passed via|
operator resulting in execution of echo c.
$ asd |echo c
c
zsh: command not found: asd
asd
fails resulting inecho b
not being executed with overall statuscode1
. So,||
being theor
boolean operator executes second halfecho c
.
$ asd && echo b || echo c
zsh: command not found: asd
c
echo true
executes. Passing true as stdin toasd
command. Butasd
fails.
$ echo true | asd
zsh: command not found: asd
- As
echo a
is async. A separate threadT
is started for it and context moves toecho b
, which prints b. ThenT
finishes and its stdout and stderr is displayed.
$ echo a & echo b
[1] 51810
b
a
[1] + 51810 done echo a
- d is created in root directory instead of the
dir
folder. This meanscd cmd
is executed indifferent environment
or as aseparate script
and its stdout is piped resulting intouch d
being executed.
This is similar to having a script a.sh
with cd dir
in it and running ./a.sh | touch d
command.
$ ls
cmd/
$ cd cmd | touch d
$ ls
cmd/ d
$ rm -rf d
$ echo cd cmd > a.sh && chmod +x a.sh
$ ./a.sh | touch d
$ ls
dir/ d
This behavior is similar to &
, but &
executes first cmd
in separate thread.
Now, why I tried to figure out how these operator differs?
Reason is I was trying to execute many commands together as one-liner. But I needed to handle error as sometimes some of the commands failed . I tried using ||
, but if first command didn't fail then next command will be skipped. I tried |
, but with cd dir | touch d
, it generated d
file in root directory instead of d
directory. As with both |
and &
, the first command is executed in a different envionment
or as a separate script
, they aren't the best solution.
Conclusion: Instead of combining commands in one line , spread them in multiple lines. :)