两者之间有什么区别
$ ls > dirlist 2>&1
和
$ ls 2>&1 > dirlist
将stderr和stdout都重定向到目录。
答案 0 :(得分:1)
Shell重定向/管道运算符按照在命令行上出现的顺序应用。一旦知道了这些信息并以正确的方式阅读了这些运算符,区别就会变得很明显,因此让我们更详细地看一下运算符:
a
重定向到b
意味着:使a
的FD与b
引用相同的内容,即重定向后,两个文件描述符可以互换使用。 (旧的a
已丢失)。在内部,这是通过dup2
系统调用发生的。>foo
用写入stdout
的句柄替换foo
2>&1
用一个句柄替换FD 2(stderr
),该句柄写入FD 1(stdout
)当时指的 。请记住,这是两种变体的情况:
>foo 2>&1
:shell打开一个新的FD,该FD写入foo
,并将stdout
重定向到它,这意味着FD 1现在写入foo
。然后,将此FD 1复制到FD 2中,隐式关闭旧FD 2(它指的是原始stderr
)。结果,两个FD都写入foo
。
2>&1 >foo
:shell首先将FD 1复制到FD 2,以便将错误写入stdout
。然后,它创建一个写入foo
的新FD,并将其复制到FD 1中。由于重定向操作符的顺序,这将覆盖FD 1,但FD 2仍引用“旧的” FD1。结果,FD 2将写入旧的stdout
(可能是您的终端),而FD 1将写入旧的foo
的{{1}}。
答案 1 :(得分:0)
不确定zsh,但根据Bash manual:
Note that the order of redirections is significant. For example, the
command
ls > dirlist 2>&1
directs both standard output and standard error to the file dirlist,
while the command
ls 2>&1 > dirlist
directs only the standard output to file dirlist, because the standard
error was duplicated as standard output before the standard output was
redirected to dirlist.
对于ls > dirlist 2>&1
,这就是发生的情况(在伪C代码中):
fd = open("dirlist");
dup2(fd, 1); // now stdout is a dup of fd so stdout points to "dirlist"
dup2(1, 2); // now stderr becomes a dup of stdout so it also points to "dirlist"
对于ls 2>&1 > dirlist
,会发生以下情况:
// initially, both stdout and stderr point to the tty
dup2(1, 2); // now stderr becomes a dup of stdout so they still point to the tty
fd = open("dirlist");
dup2(fd, 1); // now stdout is a dup of fd so stdout points to "dirlist",
// but stderr still points to tty