shell 标准流重定向顺序 OR 2>&1 1>/dev/null vs 1>/dev/null 2>&1

shell 标准流重定向顺序 OR 2>&1 1>/dev/null vs 1>/dev/null 2>&1

有人能解释一下区别吗?其中一些被视为最佳实践吗?如果我记得正确的话,我以某种方式读到这1>/dev/null应该先于这个:2>&1

ls -al /doesNotExists 2>&1 1>/dev/null
ls -al /doesNotExists 1>/dev/null 2>&1

ls -al /doesNotExists 1>&2 2>/dev/null
ls -al /doesNotExists 2>/dev/null 1>&2

ls -la /doesNotExists 2<&1 1>/dev/null
ls -la /doesNotExists 2<&1 2>/dev/null

ls -la /doesNotExists 1<&2 1>/dev/null
ls -la /doesNotExists 1<&2 2>/dev/null

ls -la /doesNotExists 1>/dev/null 2<&1
ls -la /doesNotExists 2>/dev/null 2<&1

ls -la /doesNotExists 1>/dev/null 1<&2
ls -la /doesNotExists 2>/dev/null 1<&2

答案1

shell 标准流重定向顺序

顺序很重要,因为结果不同。以第一个例子为例:

ls -al /doesNotExists 2>&1 1>/dev/null

这只会将标准输出定向到 nul,因为标准错误已复制到标准输出标准输出被重定向到 dirlist。

ls -al /doesNotExists 1>/dev/null 2>&1

这会将标准输出和标准错误都指向 nul。


Bash 参考手册:重定向

请注意,重定向的顺序很重要。例如,命令

ls > dirlist 2>&1

将标准输出(文件描述符 1)和标准错误(文件描述符 2)定向到文件 dirlist,而命令

ls 2>&1 > dirlist

仅将标准输出定向到文件 dirlist,因为在将标准输出重定向到 dirlist 之前,标准错误已成为标准输出的副本。

来源Bash 参考手册:重定向


教程

这里有一个很好的插图教程图解重定向教程这使得这一点更容易理解:

重定向的顺序,即“> file 2>&1”与“2>&1 >file”

虽然重定向在命令行上出现的位置无关紧要,但它们的顺序却很重要。它们是从左到右设置的。

2>&1 >file

一个常见的错误是执行命令 2>&1 > file 将 stderr 和 stdout 重定向到 file。让我们看看发生了什么。首先,我们在典型的终端中输入命令,描述符如下所示:

                  ---       +-----------------------+
standard input   ( 0 ) ---->| /dev/pts/5            |
                  ---       +-----------------------+

                  ---       +-----------------------+
standard output  ( 1 ) ---->| /dev/pts/5            |
                  ---       +-----------------------+

                  ---       +-----------------------+
standard error   ( 2 ) ---->| /dev/pts/5            |
                  ---       +-----------------------+

然后我们的 shell,Bash 看到 2>&1,所以它复制 1,文件描述符如下所示:

                  ---       +-----------------------+
standard input   ( 0 ) ---->| /dev/pts/5            |
                  ---       +-----------------------+

                  ---       +-----------------------+
standard output  ( 1 ) ---->| /dev/pts/5            |
                  ---       +-----------------------+

                  ---       +-----------------------+
standard error   ( 2 ) ---->| /dev/pts/5            |
                  ---       +-----------------------+

没错,什么都没有改变,2 已经指向与 1 相同的位置。现在 Bash 看到 > file 并因此更改 stdout:

                  ---       +-----------------------+
standard input   ( 0 ) ---->| /dev/pts/5            |
                  ---       +-----------------------+

                  ---       +-----------------------+
standard output  ( 1 ) ---->| file                  |
                  ---       +-----------------------+

                  ---       +-----------------------+
standard error   ( 2 ) ---->| /dev/pts/5            |
                  ---       +-----------------------+

而这并不是我们想要的。

>file 2>&1

现在让我们看看正确的命令 >file 2>&1。我们像前面的例子一样开始,Bash 看到 > file:

                  ---       +-----------------------+
standard input   ( 0 ) ---->| /dev/pts/5            |
                  ---       +-----------------------+

                  ---       +-----------------------+
standard output  ( 1 ) ---->| file                  |
                  ---       +-----------------------+

                  ---       +-----------------------+
standard error   ( 2 ) ---->| /dev/pts/5            |
                  ---       +-----------------------+

然后它看到重复的 2>&1:

                  ---       +-----------------------+
standard input   ( 0 ) ---->| /dev/pts/5            |
                  ---       +-----------------------+

                  ---       +-----------------------+
standard output  ( 1 ) ---->| file                  |
                  ---       +-----------------------+

                  ---       +-----------------------+
standard error   ( 2 ) ---->| file                  |
                  ---       +-----------------------+

瞧,1 和 2 都被重定向到文件。

相关内容