"<( cmd )" 模式在 bash 中是如何工作的?

Tha*_*wda 11 linux command-line bash

在 bash 中,我使用的参数看起来像

paste <(cat file1 | sort) <(cat file2 | sort)
Run Code Online (Sandbox Code Playgroud)

或者

comm <(cat file1 | sort) <(cat file2 | sort)
Run Code Online (Sandbox Code Playgroud)

当我检查man commor 时man paste,文档说参数确实是文件。

题:

  1. 是否为<(cat file1 | sort)和创建了中间临时文件(在 TEMP 文件系统或较慢磁盘上的其他地方)<(cat file2 | sort)?

  2. 这个<( )魔法叫什么名字?(查找其文档)

  3. 它是特定于 bash 的还是跨其他 shell 工作的?

jes*_*e_b 18

这称为进程替换。

3.5.6 进程替换

进程替换允许使用文件名引用进程的输入或输出。

进程列表异步运行,其输入或输出显示为文件名。这个文件名作为扩展的结果作为参数传递给当前命令。如果使用 >(list) 形式,写入文件将为列表提供输入。如果使用 <(list) 形式,则应读取作为参数传递的文件以获得 list 的输出。请注意,< 或 > 和左括号之间不能出现空格,否则该构造将被解释为重定向。在支持命名管道 (FIFO) 或命名打开文件的 /dev/fd 方法的系统上支持进程替换。

它不仅仅是最初出现在 ksh 中的 bash 东西,而且不在 posix 标准中。

在幕后,进程替换有两种实现。在支持/dev/fd(大多数类 Unix 系统)的系统上,它通过调用pipe() 系统调用来工作,该调用返回$fd一个新匿名管道的文件描述符,然后创建 string /dev/fd/$fd,并在命令行上替换它。在不/dev/fd支持的系统上,它调用mkfifo一个新的临时文件名来创建一个命名管道,并在命令行上替换这个文件名。

  • 这也出现在 zsh 中。令我惊讶的是,[大多数其他 shell 不这样做](https://en.wikipedia.org/wiki/Comparison_of_command_shells#Inter-process_communication) 尽管进程替换在各种情况下都非常有用。 (2认同)

Kus*_*nda 7

您可以将其<( somecommand )视为包含输出的临时文件的文件名somecommand。换句话说,

utility < <( somecommand )
Run Code Online (Sandbox Code Playgroud)

是捷径

somecommand >tempfile
utility <tempfile
rm -f tempfile
Run Code Online (Sandbox Code Playgroud)

和

utility <( somecommand )
Run Code Online (Sandbox Code Playgroud)

是捷径

somecommand >tempfile
utility tempfile  # notice the lack of redirection here (utility expected to read from "tempfile")
rm -f tempfile
Run Code Online (Sandbox Code Playgroud)

同样>( somecommand )可以被认为是一个临时文件的文件名,它将被输入到somecommand它的标准输入中。换句话说,

utility > >( somecommand )
Run Code Online (Sandbox Code Playgroud)

是捷径

utility >tempfile
somecommand <tempfile
rm -f tempfile
Run Code Online (Sandbox Code Playgroud)

和

utility >( somecommand )
Run Code Online (Sandbox Code Playgroud)

可能是捷径

mkfifo temppipe
somecommand <temppipe &
utility temppipe  # utility is expected to write to "temppipe"
rm -f temppipe
Run Code Online (Sandbox Code Playgroud)

(或类似的东西)

  • 就目前而言,这是正确的,但您应该清楚,在所有情况下都使用管道,而不是实际的临时文件。这很重要,因为这意味着尝试在文件中寻找的程序将无法处理进程替换。 (2认同)