我正在玩i / o shell重定向。我尝试过的命令(在bash中):
ls -al *.xyz 2>&1 1> files.lst
和
ls -al *.xyz 1> files.lst 2>&1
当前文件夹中没有任何*.xyz
文件。
这些命令给了我不同的结果。第一个命令在屏幕上显示错误消息ls: *.xyz: No such file or directory
。但第二个将此错误消息打印到该文件。为什么第一个命令无法将错误的输出写入文件?
答案 0 :(得分:31)
Bash manual有一个明显的例子(与你的类似),以表明订单很重要,也解释了差异。这里摘录了相关部分(强调我的):
请注意,重定向的顺序非常重要。例如, 命令
ls> dirlist 2>& 1
指示标准输出(文件描述符1)和标准错误 (文件描述符2)到文件 dirlist ,而命令
ls 2>& 1> dirlist
仅将标准输出定向到文件 dirlist ,因为标准 错误是标准之前的标准输出的副本 输出被重定向到 dirlist 。
This post从POSIX观点解释。
由于关键差异而发生混淆。 >
通过使左操作数(stderr
)指向右操作数(stdout
)重定向而不是,但是通过复制右操作数并将其分配给剩下。从概念上讲,通过复制而不是通过引用进行分配。
因此,从左到右阅读Bash解释了这一点:ls > dirlist 2>&1
表示将stdout
重定向到文件dirlist
,然后重定向stderr
到目前的任何stdout
(已经是文件dirlist
)。但是,ls 2>&1 > dirlist
会将stderr
重定向到当前stdout
(屏幕/终端),然后将stdout
重定向到dirlist
。
答案 1 :(得分:17)
重定向是:
1
用于stdout(默认值),2
用于stderr),则稍后重定向将针对该流引用到已经重定向的版本。1
作为目标,则1
表示当时被锁定,即使{{1}稍后重定向。应用于问题中的示例:
1
:
>file 2>&1
首先重定向stdout(文件描述符>file
,暗示为1
不带前缀文件描述符号)到输出文件>
file
然后将stderr(2>&1
)重定向到已重定向的标准输出(2
)。1
。 file
:
2>&1 >file
首先将stderr重定向到 then-original 标准输出;由于文件描述符2>&1
不参与进一步的重定向,因此stderr输出将转到那个被定义为的stdout - 即,原始的标准输出,给定这是第一次重定向。
2
然后将原始标准输出重定向到>file
- 但这对已经锁定的stderr重定向没有任何影响。file
中捕获了直接发送到stdout的输出,而发送到stderr的输出则输出到(原始的,未重定向的)stdout。答案 2 :(得分:12)
此错误:
ls: *.xyz: No such file or directory
由stderr
二进制文件写在ls
上。
但是在这个命令中:
ls -al *.xyz 2>&1 1> files.lst
您首先将 stderr
重定向到stdout
,默认情况下转到tty
(终端)
然后您将stdout
重定向到文件files.lst
,但请记住stderr未重定向到文件,因为您有stderr
到stdout
重定向 stdout
到file
重定向之前。在这种情况下,stderr
仍会写入tty
。
但是在第二种情况下,您可以更改重定向的顺序(首先stdout
到file
,然后stderr
更改为stdout
)并正确地将stderr
重定向到file
也使用了stdout
。
答案 3 :(得分:2)
因为订单很重要。 在第一种情况下,首先将stderr(2)重定向到stdout(1)。 然后重定向(1)到文件。但是stderr(2)仍然指向运行命令的shell的stdout。在这种情况下将(1)指向文件不会改变(2)所针对的输出设备,因此它仍然会转到终端。
在第二种情况下,将stdout(1)重定向到文件。然后你将stderr(2)指向相同的位置1,这是文件,因此错误消息将转到文件。