2010-03-14 97 views
17

当通过文件夹包含空格我用的shell脚本是这种形式,从internet复制的文件递归循环:“<(cmd args)”在shell中的含义是什么?

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

我想我明白了IFS位,但我不明白什么是“ < <(...)'字符的意思。显然这里有一些管道。

这很难让Google“< <”,你看。

+0

难道你不是指“<<”? – reinierpost 2010-03-14 17:51:34

+0

无论如何,“man sh”是你的朋友。 – reinierpost 2010-03-14 17:52:05

+4

它不是'<<',它是'<和'<(...)'运营商,如果我记得没错 – 2010-03-14 17:55:37

回答

23

<()在手册中被称为process substitution,类似于管道,但传递的格式为/dev/fd/63而不是stdin。

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

一起,这两个操作员功能完全一样的管,因此它可以被重写为

find /bar -name *foo* -print0 | while read line; do 
    ... 
done 
+8

如果您不能启动一个子shell – knittl 2010-03-14 18:18:28

+6

+1,这是不一样的,因为您的符号名称是正确的。正如@ knittl指出的那样,它与重写不完全相同,因为循环将运行在子shell中,循环中变量所做的任何更改仅影响子shell,而不影响主脚本。你可以通过将'find'的输出重定向到''{while ...;做...;完成; ...脚本的其余部分...; }',使用大括号将整个脚本的其余部分(循环和其他材质)分组到一个子shell中。 – 2010-03-14 18:39:57

+1

谢谢你。我可以感觉到我的头骨扩展到执行shell脚本的大脑部分。有一个精确的术语谷歌使得它更容易。现在我要去了解一下子shell是什么。 – stib 2010-03-15 10:46:40

-3

<<运营商引入了here-document,它将另一个命令的输出作为第一个命令的输入。

更新

好了,所以他们必须添加一些东西的外壳,因为我去年15年前使用过它。
请不要理会。

4

<重定向到标准输入。

<()似乎是某种反向管道,在页面上提到:

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

将无法​​正常工作,因为while循环将在一个子shell执行,你会失去所做的更改在循环中

+0

这个答案会受益于x-ref'流程替换'和一个像http://www.gnu.org/software/bash/manual/bashref.html#Process-Substitution这样的URL来解释它。关键点是子外壳和对子外壳中的变量所做的更改。处理它的另一种方式是:'find ... | {while ...;做...;完成; ...脚本的其余部分...; }',使用大括号在一个子shell,而不是仅仅while循环运行的脚本的所有的休息。 – 2010-03-14 18:35:49

3

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

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 /不管像文本文件一样圆括号之间的命令的输出。