为什么2&& 1必须在|之前出现(管道),但在“"之后myfile" (重定向到文件)? [英] Why does 2>&1 need to come before a | (pipe) but after a "> myfile" (redirect to file)?

查看:70
本文介绍了为什么2&& 1必须在|之前出现(管道),但在“"之后myfile" (重定向到文件)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

将stderr与stdout结合使用时,为什么2>&1需要在|(管道)之前但在> myfile(重定向到文件)之后?

要将stderr重定向到stdout以输出文件:

  echo > myfile 2>&1

要将stderr重定向到管道的stdout:

  echo 2>&1 | less



我的假设是我可以做:

  echo | less 2>&1 

,它可以工作,但不能.为什么不呢?

解决方案

管道命令的|分隔列表.您指定的任何重定向都适用于组成命令(简单或复合),但不适用于整个管道.每个管道通过隐式将重定向应用于每个子外壳之前,将与一个命令关联的任何重定向求值,从而将一个命令的stdout链接到下一命令的stdin.

cmd 2>&1 | less

第一个子shell的第一个stdout重定向到正在读取less的管道.接下来,将2>&1重定向应用于第一个命令.将stderr重定向到stdout起作用,因为stdout已经指向管道.

cmd | less 2>&1

此处,重定向适用于less. Less的stdout和stderr可能都是以指向终端的方式开始的,因此2>&1在这种情况下无效.

如果您希望重定向应用于整个管道,将多个命令作为管道的一部分进行分组或嵌套管道,请使用命令组(或任何其他 compound命令):

{ { cmd1 >&3; cmd2; } 2>&1 | cmd3; } 3>&2

可能是一个典型的例子.最终结果是:cmd1cmd2的stderr-> cmd3; cmd2的标准输出-> cmd3;和cmd1cmd3的stderr,以及cmd3的stdout->终端.

如果使用特定于Bash的|&管道,事情会变得很奇怪,因为每个管道的stdout重定向仍然首先发生,但stderr重定向实际上是最后发生.例如:

f() { echo out; echo err >&2; }; f >/dev/null |& cat

现在,与直觉相反,所有输出都被隐藏. f的第一个stdout进入管道,f的下一个stdout重定向到/dev/null,最后,stderr重定向到stdout(仍然是/dev/null).

我建议不要在Bash中使用|& -在这里用于演示.

When combining stderr with stdout, why does 2>&1 need to come before a | (pipe) but after a > myfile (redirect to file)?

To redirect stderr to stdout for file output:

  echo > myfile 2>&1

To redirect stderr to stdout for a pipe:

  echo 2>&1 | less



My assumption was that I could just do:

  echo | less 2>&1 

and it would work, but it doesn't. Why not?

解决方案

A pipeline is a |-delimited list of commands. Any redirections you specify apply to the constituent commands (simple or compound), but not to the pipeline as a whole. Each pipe chains one command's stdout to the stdin of the next by implicitly applying a redirect to each subshell before any redirects associated with a command are evaluated.

cmd 2>&1 | less

First stdout of the first subshell is redirected to the pipe from which less is reading. Next, the 2>&1 redirect is applied to the first command. Redirecting stderr to stdout works because stdout is already pointing at the pipe.

cmd | less 2>&1

Here, the redirect applies to less. Less's stdout and stderr both presumably started out pointed at the terminal, so 2>&1 in this case has no effect.

If you want a redirect to apply to an entire pipeline, to group multiple commands as part of a pipeline, or to nest pipelines, then use a command group (or any other compound command):

{ { cmd1 >&3; cmd2; } 2>&1 | cmd3; } 3>&2

Might be a typical example. The end result is: cmd1 and cmd2's stderr -> cmd3; cmd2's stdout -> cmd3; and cmd1 and cmd3's stderr, and cmd3's stdout -> the terminal.

If you use the Bash-specific |& pipe, things get stranger, because each of the pipeline's stdout redirects still occur first, but the stderr redirect actually comes last. So for example:

f() { echo out; echo err >&2; }; f >/dev/null |& cat

Now, counterintuitively, all output is hidden. First stdout of f goes to the pipe, next stdout of f is redirected to /dev/null, and finally, stderr is redirected to stdout (/dev/null still).

I recommend never using |& in Bash -- it's used here for demonstration.

这篇关于为什么2&& 1必须在|之前出现(管道),但在“"之后myfile" (重定向到文件)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆