如何理解输出重定向的顺序?
所以我正在努力学习如何将标准输出和标准错误传递到各个领域。
假设我只有here.txt
的文件夹。
所以,如果我这样做
ls here.txt not-here.txt 1>out 2>&1
由于here.txt
存在,我将有一些输出指向文件out
但由于not-here.txt
不存在,错误将通过标准错误发送,我将重定向到标准输出2>&1
。
但是,为什么这不起作用:
ls here.txt not-here.txt 2>&1 1>out
似乎只有在标准输出指令后进行重定向才能工作? 为什么?
重定向的顺序很重要 。 例如,命令
ls > dirlist 2>&1
在命令时将标准输出和标准错误都指向文件dirlist
ls 2>&1 > dirlist
仅将标准输出指向文件dirlist,因为在标准输出重定向到dirlist之前,标准错误从标准输出(通常仍指向终端窗口)复制。
起初这可能会让人感到反直觉,但在考虑之后,我们可以理解它。
你可以在man bash
找到关于重定向的章节中的这个解释,
REDIRECTION
在执行命令之前,可以使用shell解释的特殊表示法重定向其输入和输出。 重定向允许复制,打开,关闭命令文件句柄,使其引用不同的文件,并可以更改命令读取和写入的文件。 重定向还可用于修改当前shell执行环境中的文件句柄。 以下重定向运算符可以在简单命令之前或出现在任何位置,也可以跟随命令。 重定向按其出现的顺序从左到右处理。
可以在文件描述符号之前的每个重定向可以改为在
{varname}
forms的单词之后。 在这种情况下,对于除>&-
和<&-
之外的每个重定向运算符,shell将分配大于或等于10的文件描述符并将其分配给varname
。 如果>&-
或<&-
前面有{varname}
,则varname
的值定义要关闭的文件描述符。在以下描述中,如果省略文件描述符号,并且重定向运算符的第一个字符是
<
,则重定向指的是标准输入(文件描述符0)。 如果重定向运算符的第一个字符是>
,则重定向引用标准输出(文件描述符1)。除非另有说明,否则以下描述中的重定向运算符后面的单词将受到括号扩展,波形扩展,参数和变量扩展,命令替换,算术扩展,引用删除,路径名扩展和单词拆分的影响。 如果它扩展为多个单词,bash会报告错误。
请注意,重定向的顺序很重要。 例如,命令
ls > dirlist 2>&1
在命令时将标准输出和标准错误都指向文件
dirlist
ls 2>&1 > dirlist
仅将标准输出指向文件
dirlist
,因为在将标准输出重定向到dirlist
之前,标准错误与标准输出重复。
编辑:以下命令行可以解释会发生什么
准备
sudodus@xenial32:~$ touch qwerty;rm asdf rm: cannot remove 'asdf': No such file or directory
对一个现有文件和一个不存在的文件运行list命令
sudodus@xenial32:~$ ls qwerty asdf ls: cannot access 'asdf': No such file or directory qwerty
在重定向标准输出之前重定向错误输出。 只有标准输出被重定向到输出文件。
sudodus@xenial32:~$ ls qwerty asdf 2>&1 > output-file ;echo '---';cat output-file ls: cannot access 'asdf': No such file or directory --- qwerty
重定向标准输出后重定向错误输出。 错误输出和标准输出都被重定向到输出文件。
sudodus@xenial32:~$ ls qwerty asdf > output-file 2>&1 ;echo '---';cat output-file --- ls: cannot access 'asdf': No such file or directory qwerty
令牌&>
可用于重定向标准错误和标准输出。 它可以在bash
,但可能在其他shell中不可用。
sudodus@xenial32:~$ ls qwerty asdf &> output-file ;echo '---';cat output-file --- ls: cannot access 'asdf': No such file or directory qwerty sudodus@xenial32:~$
-
2>x
表示文件名x
将接收写入描述符2
的数据(也称为stderr,标准错误) - …但是当
x
指定为&1
它并不意味着“始终跟随1
”; 它意味着“复制1的当前属性(然后不管它)” 。 - 重定向的应用顺序与在命令行中输入的顺序相同,但在实际执行之前。
这就是为什么2>&1 1>whatever
输出stderr到终端的原因。
这就是find / -name mylostfile.txt 3>&1 1>&2 2>&3 | grep -v 'Permission denied'
find / -name mylostfile.txt 3>&1 1>&2 2>&3 | grep -v 'Permission denied'
交换stderr和stderr,这样你就可以过滤掉一些常见的stderr行,但仍然可以看到所有的stdout。 (这里的描述符3未被程序使用)。
shell会按照它看到的顺序遇到并设置。 在第一种情况下:
ls here.txt not-here.txt 1>out 2>&1
输出被重定向,然后标准错误被发送到同一个地方。
在第二种情况下,
ls here.txt not-here.txt 2>&1 1>out
标准输出仍然设置到终端,因此标准错误被发送到终端THEN标准输出被更改。 shell已经设置了标准错误。