《Ubuntu — 2>/dev/null和>/dev/null 2>&1和2>&1>/dev/null的区别》
1.区别
2>/dev/null
意思就是把错误输出到“黑洞”。
>/dev/null 2>&1
默认情况是1,也就是等同于1>/dev/null 2>&1。意思就是把标准输出重定向到“黑洞”,还把错误输出2重定向到标准输出1,也就是标准输出和错误输出都进了“黑洞”。
2>&1 >/dev/null
意思就是把错误输出2重定向到标准出书1,也就是屏幕,标准输出进了“黑洞”,也就是标准输出进了黑洞,错误输出打印到屏幕。
乍一看>/dev/null 2>&1和2>&1 >/dev/null应该是一样的效果。但是为什么会不一样呢?
linux在执行shell命令之前,就会确定好所有的输入输出位置,并且从左到右依次执行重定向的命令。那么我们同样从左到右地来分析 2>&1>/dev/null
:
2>&1 将错误输出绑定到标准输出上。由于此时的标准输出是默认值,也就是输出到屏幕,所以错误输出会输出到屏幕。 >/dev/null 将标准输出1重定向到/dev/null中。
我们用一个表格来更好地说明这两条命令的区别:
为什么要用重定向绑定,而不是像 >/dev/null 2>/dev/null?
我们回到刚才介绍输出重定向的场景。我们尝试将标准输出和错误输出都定向到out文件中:
# ls a.txt b.txt >out 2>out# cat out a.txt �法访问b.txt:没有那个文件或目录
出现了乱码,这是为啥呢?这是因为采用这种写法,标准输出和错误输出会抢占往out文件的管道,所以可能会导致输出内容的时候出现缺失、覆盖等情况。现在是出现了乱码,有时候也有可能出现只有error信息或者只有正常信息的情况。不管怎么说,采用这种写法,最后的情况是无法预估的。
而且,由于out文件被打开了两次,两个文件描述符会抢占性的往文件中输出内容,所以整体 IO 效率不如 >/dev/null2>&1来得高。
2. 解释
2.1、文件描述符
Linux系统预留可三个文件描述符:0、1和2,他们的意义如下所示:
- 0——标准输入(stdin)
- 1——标准输出(stdout)
- 2——标准错误(stderr)
标准输出——stdout
假设:在当前目录下,有且只有一个文件名称为ljl.txt的文件,这时我们运行这个命令【ls ljl.txt】,就会获得一个标准输出stdout的输出结果:ljl.txt。
错误输出——stderr
按照上面的假设,我们运行另一条命令【ls gss.txt】,这样我们就会获得一个标准错误stderr的输出结果“ls:无法访问gss.txt:没有那个文件或目录”。
2.2、重定向
重定向的符号有两个:>或>>,两者的区别是:前者会先清空文件,然后再写入内容,后者会将重定向的内容追加到现有文件的尾部。举个例子:
(1)、重定向标准输出stdout
如上图所示,对比没有添加重定向的操作,这条命令在使用之后并没有将123.txt打印到屏幕。在紧接的cat操作后,可以发现本来应该被输出的内容被记录到stdout.txt中。
(2)、重定向标准错误stderr
如上图所示,文件描述符2,标准错误的重定向也是同样的原理被记录在了文件stderr.txt这个文件里面了。
2.2、重定向绑定
2>&1
这条命令用到了重定向绑定,采用&可以将两个输出绑定在一起。这条命令的作用是错误输出将和标准输出同用一个文件描述符,说人话就是错误输出将会和标准输出输出到同一个地方。