我想将标准输出发送到多个命令,但是我不确定如何从进程替换中的标准输入读取?
我的尝试:
$ echo foo >(cat /dev/stdin) >(cat /dev/stdin)
foo /dev/fd/63 /dev/fd/62
$ echo foo >(cat -) >(cat -)
foo /dev/fd/63 /dev/fd/62
$ echo foo >(cat <&3) >(cat <&3) 3<&0
foo /dev/fd/63 /dev/fd/62
-bash: 3: Bad file descriptor
-bash: 3: Bad file descriptor
同一问题的替代版本:
$ cat file | tee &>/dev/null >(cmd1 /dev/stdin) >(cmd2 /dev/stdin)
这样做的正确方法是什么?
答案1
这是从标准输入读取的:
echo foo | tee >(read line </dev/stdin; echo "internal $line")
您必须记住,进程替换的行为“就像”文件。
它可以用在需要文件的地方。命令 tee 期望写入文件。
在该命令中,我们具体指定要读取的设备:/dev/stdin。在这个简单的例子中,/dev/stdin 可以被删除,这也将起作用:
echo foo | tee >(read line; echo "internal $line")
如果我正确理解您的需求,这将会起作用:
$ echo foo | tee >(read a </dev/stdin; echo "a is $a") \
>(read b </dev/stdin; echo "b is $b") \
>(read c </dev/stdin; echo "c is $c")
foo
a is foo
c is foo
b is foo
我省略了 PS2 提示以减少混乱。请注意,每个进程替换都会替换文件的使用(如tee FILE FILE ....
:)。
读取不一定是第一个命令。
$ echo foo > >(echo "hello" | read b; read a </dev/stdin; echo "a is $a")
a is foo
请注意,这里的“进程替换”需要重定向,
这就是这两个习惯用法的原因> >(
。
一个简单的 echo,只会打印所使用的 fd 的编号(文件名):
$ echo >(echo "hello")
/dev/fd/63
hello
它类似于:
$ echo "$file"
filename
然而这是一个非常不同的习语:
$ echo > "$file"