Shell 重定向:

Shell 重定向:

我已经看到了这两种方法<<<'foo',并<(echo 'foo')建议将其作为回显管道的替代方案(echo foo | cat)。

当我将这两个结构与 cat 一起使用时,我得到:

$ cat <<<'foo'
foo
$ cat <(echo 'foo')
foo

到目前为止,也是如此。

然而,当您直接在 shell 上使用它们时,差异就会变得明显:

$ <<<'foo'
foo
$ <(echo 'foo')
zsh: permission denied: /dev/fd/12

我正在使用 zsh,而 bash 似乎以<<<不同的方式处理这种情况,根本不打印任何内容,但与这种情况下的 zsh 相同<()

但真正引发我问题的是一个差异:

$ diff <<<"/mypath" <(pwd)
diff: missing operand after `/dev/fd/63'
diff: Try `diff --help' for more information.

很明显,这两种类型的 shell 重定向之间存在根本区别。谁能解释其中的区别吗?

答案1

<<< text是一个重定向,如果影响命令的文件描述符(这里是 0,但4<<< text会影响 fd 4)。

while<(...)是扩展/替换,而不是重定向。它扩展为文件名。如果插入到命令中,这会影响传递给命令的参数。

cat <(echo test)

cat使用类似文件作为参数运行/dev/fd/12。而且它的 fd 12 在管道的读取端也是打开的。cat不会从它的 fd 12 中读取,但是当它打开文件时/dev/fd/12,它将获得一个新的 fd(可能是 3),它指向与 fd 12 相同的管道。

同时echo test在后台运行,其 fd 1 连接到同一管道的写入端,因此echocat最终将通过该管道进行连接(尽管该通信通道的建立比 更复杂echo text | cat)。

cat <<< text

运行不带参数的 cat 并打开其 fd 0 以读取包含test\n.

zsh 解释

<<< test

作为

$NULLCMD <<< test

$NULLCMD通常是cat)每当您运行仅包含重定向的内容时都会发生这种情况(除非只有一个<重定向,在这种情况下$READNULLCMD(通常是寻呼机)会被使用))。

在:

<(echo text)

没有重定向,只有一个进程替换,扩展为一个 /dev/fd/12 参数。这就是要求 shell 执行该文件。

在 zsh 中,使用以下命令并没有真正的好处:

cat <(echo test)
cat < <(echo test)

超过

echo test | cat

您可以在其他 shell(例如 bash)中看到此构造,例如:

IFS= read -r var < <(echo text)

但那是因为在这些 shell 中,echo text | IFS= read -r var它不起作用,因为read它是在子进程中运行的。情况并非如此zsh

进程替换对于仅接受通过文件名作为参数(而不是通过标准输入)输入的命令非常有用,当您需要将多个输入传递给命令(只有一个标准输入)时,就像diff <(cmd1) <(cmd2).

zsh之间的一个区别是,后者不等待。虽然它确实等待和in (如果只是为了使两个退出状态都可用)。与相比。cmd1 | cmd2cmd2 < <(cmd1)zshcmd1cmd1cmd2cmd1 | cmd2$pipestatussleep 1 | unameuname < <(sleep 1)

cmd <<< foocmd当需要能够查找其输入时会很有用(因为在 中zsh,像此处文档这样的此处字符串是使用临时文件而不是管道实现的)。

相关内容