令人费解的 Bash 语法——重定向到循环

Puzzling Bash syntax -- redirect into loop

运行 通过 shellcheck.net 的脚本有人告诉我 "for loops over find output are fragile." 很公平,带空格的文件名总是很棘手。

建议的替换代码(其中之一)是这样的:

while IFS= read -r -d '' file
do
    #do stuff
done <   <(find . -name '*' -print0)

我熟悉用于将文本从文件输入到命令的 < 运算符,显然 find 的结果被送入循环。因此,当我第一次看到它时,我认为它是某些格式问题的受害者,并尝试 "cleaning up" 最后一行。但是删除 < < 之间的空格会导致语法错误,在 <(.

中添加一个也是如此

那么 < <(cmd) 结构在做什么?很抱歉,如果这是一个简单或多余的问题,搜索这些东西并不容易!

你说的<就是input redirection

<(Process Substitution

Process substitution is supported on systems that support named pipes (FIFOs) or the /dev/fd method of naming open files. It takes the form of

<(list)

or

>(list)

The process list is run with its input or output connected to a FIFO or some file in /dev/fd. The name of this file is passed as an argument to the current command as the result of the expansion. If the >(list) form is used, writing to the file will provide input for list. If the <(list) form is used, the file passed as an argument should be read to obtain the output of list. Note that no space may appear between the < or > and the left parenthesis, otherwise the construct would be interpreted as a redirection.

When available, process substitution is performed simultaneously with parameter and variable expansion, command substitution, and arithmetic expansion.

您不能将两个 < 标记组合起来,因为这样就变成了 here document 标记。

您不能在 <( 之间添加 space,因为这样它就不再是进程替换标记。

bash 中的 while 循环是复合命令的示例。与任何其他命令一样,它有自己的标准输入。它实际上根本不从中读取,但是 while 循环中的任何命令 运行 将从循环中继承其标准输入。

在此示例中,read 命令将从 find 命令的输出中读取。


<(find ...) 进程替换 的示例。 find 命令是 运行,<(...) 被视为一个文件,其内容是 find 命令的输出。 while 循环(因此 read)使用的正是这个 "file" 作为标准输入。