在Bash中,"<()"是什么意思?

20

我正在尝试安装RVM。这里有一个神奇的命令行:

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

我知道bash和curl是什么。我知道第一个<是I/O重定向符号。但是<()语法是什么意思呢?

这个命令和下面的命令有什么区别?

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

?(后一条命令无法运行)


16
我不知道,但它看起来像一只企鹅! - tomasz
在你的第二个例子中,你的命令扩展为一个字符串,bash 尝试将其连接到进程的输入流。尝试使用 cat < somefile 来理解和 cat < <(echo test)。它可能会显示 X 文件不存在 - Lynch
@tomasz:正是我所思考的(“)> - PengOne
3
请注意,如果您使用此语法,它可能会在您的 /tmp/ 目录中留下一个命名管道;即使进程终止后也是如此。因此,您还需要一些方案来清理您的 /tmp/ 目录。 - Be Kind To New Users
4个回答

20

这是bash的进程替换

表达式<(list)将被一个文件名替换,可以是命名FIFO或者/dev/fd下的条目。所以要从中重定向输入,你必须使用< <(list)

[编辑;忘记回答你的第二个问题了]

反引号称为命令替换。与进程替换不同,它是POSIX shell规范的一部分(即不是bash扩展)。Shell在反引号中运行命令,并在命令行上替换其输出。因此,这是有意义的:

cat < `echo /etc/termcap`

但这不会:
cat < `cat /etc/termcap`

后者与您的示例类似;它试图使用命令的(复杂的)输出作为文件名,从中重定向标准输入。

7
其他人已经很好地回答了你的问题,我只是想加一个例子来进一步说明... 当我个人使用 <() 时,99% 的情况下是为了同时比较两个不同命令的输出。例如, diff <( some_command ) <( some_other_command )

4
io重定向的语法如下:
process < file

因此,您需要在io重定向后出现文件名。
反引号扩展将命令的结果直接放入命令行中。因此,
 `curl -s https://rvm.io/install/rvm`

会被扩展为类似于#!/usr/bin/env bash的内容...

如果这样,shell会感到困惑,因为它会看到

 bash < #... 

与其使用文件名,<() 操作符会创建一个新的进程在 (..) 中运行命令。它将创建一个新的文件或管道来捕获结果。箭头指向左边 <() 而不是 >(),这意味着内部进程的输出将被写入文件,可以被进程读取。

在您的情况下,bash < <(...) 就像 bash < /dev/fd/100 一样。

如果您确实想知道发生了什么,请运行

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

3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接