Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between x | y and y <(x) in bash?

Tags:

bash

pipe

Is there a difference between command1 | command2 and command2 <(command1)?

For example, git diff | more vs more <(git diff)

My understanding is that both take the stdout of command2 and pipe it to the stdin of command1.

like image 977
Christopher Shroba Avatar asked Jul 15 '16 18:07

Christopher Shroba


1 Answers

The main difference is that <(...), called "process substitution", is translated by the shell into a filename that is passed as a regular argument to the command; it doesn't send anything to the command's standard input. This means that it can't be used directly with commands such as tr which don't take a filename argument:

$ tr a-z A-Z <(echo hello)
usage: tr [-Ccsu] string1 string2
       tr [-Ccu] -d string1
       tr [-Ccu] -s string1
       tr [-Ccu] -ds string1 string2

However, you can always put another < in front of the <(...) to turn it into an input redirection instead:

$ tr a-z A-Z < <(echo hello)
HELLO 

And because it generates a filename, you can use process substitution with commands that take more than one file argument:

$ diff -u <(echo $'foo\nbar\nbaz') <(echo $'foo\nbaz\nzoo')
--- /dev/fd/63  2016-07-15 14:48:52.000000000 -0400
+++ /dev/fd/62  2016-07-15 14:48:52.000000000 -0400
@@ -1,3 +1,3 @@
 foo
-bar
 baz
+zoo

The other significant difference is that a pipe creates subshells which can't have side effects in the parent environment:

 $ echo hello | read x
 $ echo $x
 # nothing - x is not set

But with process substitution, only the process inside the parentheses is in a subshell; the surrounding command can still have side effects:

 $ read x < <(echo hello)
 $ echo $x
 hello

Worth mentioning that you can also write into a process with >(...), although there are fewer cases where that's useful:

$ echo hello > >(cat)
hello
like image 125
Mark Reed Avatar answered Oct 21 '22 13:10

Mark Reed