51

当递归遍历包含空格的文件的文件夹时,我使用的 shell 脚本是这种形式,从互联网复制:

    while IFS= read -r -d $'\0' file; do
      dosomethingwith "$file"        # do something with each file
    done < <(find /bar -name *foo* -print0)

我想我理解 IFS 位,但我不明白 ' < <(...)' 字符的含义。显然这里有某种管道。

谷歌搜索“< <”或“<(”非常困难,你看。我尝试了“尖括号括号”和“小于括号”但没有找到任何东西。

4

3 回答 3

58

<()在手册中称为进程替换,类似于管道,但传递表单的参数/dev/fd/63而不是使用标准输入。

<从命令行命名的文件中读取输入。

一起,这两个运算符的功能就像一个管道,所以它可以重写为

find /bar -name *foo* -print0 | while read line; do
  ...
done
于 2010-03-14T18:00:18.087 回答
14

<( command ) 是进程替换。基本上,它创建一种称为“命名管道”的特殊类型的文件,然后将命令的输出重定向到命名管道。例如,假设您想要翻阅一个超大目录中的文件列表。你可以这样做:

ls /usr/bin | more

或这个:

more <( ls /usr/bin )

但不是这个:

more $( ls /usr/bin )

当您进一步调查时,其原因会变得很清楚:

~$ echo $( ls /tmp )
gedit.maxtothemax.436748151 keyring-e0fuHW mintUpdate orbit-gdm orbit-maxtothemax plugtmp pulse-DE9F3Ei96ibD pulse-PKdhtXMmr18n ssh-wKHyBU1713 virtual-maxtothemax.yeF3Jo
~$ echo <( ls /tmp )
/dev/fd/63
~$ cat <( ls /tmp )
gedit.maxtothemax.436748151
keyring-e0fuHW
mintUpdate
orbit-gdm
orbit-maxtothemax
plugtmp
pulse-DE9F3Ei96ibD
pulse-PKdhtXMmr18n
ssh-wKHyBU1713
virtual-maxtothemax.yeF3Jo

/dev/fd/whatever 就像一个文本文件,括号之间是命令的输出。

于 2010-03-14T22:55:50.633 回答
4

<重定向到标准输入。

<()似乎是某种反向管道,如页面所述:

find /bar -name *foo* -print0 | \
while IFS= read -r -d $'\0' file; do
  dosomethingwith "$file"        # do something with each file
done

将不起作用,因为 while 循环将在子 shell 中执行,并且您将丢失在循环中所做的更改

于 2010-03-14T17:57:35.897 回答