Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

what does "<()" mean in bash?

I'm trying to install RVM. There is a magical command line:

bash < <(curl -s https://rvm.io/install/rvm)

I know what bash and curl are. I know the first < is the I/O redirection. But what does <() syntax mean?

What's the difference between this command and

bash < `curl -s https://rvm.io/install/rvm`

?(the latter command doesn't work)

like image 825
Lai Yu-Hsuan Avatar asked Jul 19 '11 18:07

Lai Yu-Hsuan


3 Answers

This is bash's process substitution.

The expression <(list) gets replaced by a file name, either a named FIFO or an entry under /dev/fd. So to actually redirect input from it, you have to use < <(list).

[edit; forgot to answer your second question]

The backticks are called "command substitution". Unlike process substitution, it is part of the POSIX shell specification (i.e., not a bash extension). The shell runs the command in the backticks and substitutes its output on the command line. So this would make sense:

cat < `echo /etc/termcap`

But this would not:

cat < `cat /etc/termcap`

The latter is similar to your example; it tries to use the (complex) output of a command as a file name from which to redirect standard input.

like image 142
Nemo Avatar answered Oct 31 '22 20:10

Nemo


The others have already answered your question very nicely. I'll just add an example to build on them... 99% of the time when I personally use <(), it's to diff the output of two different commands in one shot. For instance,

diff <( some_command ) <( some_other_command )

like image 22
Costa Avatar answered Oct 31 '22 19:10

Costa


The syntax for io redirection is

process < file

Hence you need whatever appears after the io redirect to be a filename.

The backtick expansion literally puts the results of the command into the command line. Thus,

 `curl -s https://rvm.io/install/rvm`

expands to something like #!/usr/bin/env bash ...

and the shell would be confused because it would see

 bash < #... 

instead of a filename.

the <() operator is process substitution, which spawns a new process to run the command within the (..). A new file or pipe is created that will capture the result. The fact that the arrow is pointing left <() instead of >() means that the output from the inner process will be written to the file, which can be read by the process.

In your case, bash < <(...) will be seen as something like bash < /dev/fd/100

If you actually want to see what is going on, run

echo <(curl -s https://rvm.io/install/rvm)
like image 4
Foo Bah Avatar answered Oct 31 '22 19:10

Foo Bah