最近在学习MIT 的一门课叫做6.NULL,在exercise部分看到一个>&2 表示符,作为小白的我又懵逼了,这是个什么意思呢?在一顿搜索之后,才知道这是一种特别的重定向,下面结合别人的讲述以及自己的理解,来做个总结,有不对的地方也希望读者朋友们积极批评指正。
当我们在linux执行某个程序或者命令时,都会至少打开如下3个文件描述符。
0:标准输入(stdin)
1:标准输出(stdout)
2:标准错误输出(stderr)
这里我来主要讨论一下1和2,即标准输出和标准错误输出。当我们在shell执行某个命令时,比如下面这个简单的正确命令时
$ echo hello world
对于标准输出(1)而言,输出即为hello world。对于标准错误输出(2)而言,因为这个命令本身没有问题,对于2而言即没有任何输出。
OK,现在假设我们想要对输出做一个基本的重定向,使用> 将输出内容写入某个文件中,比如叫hello.txt
$ echo hello world > hello.txt
很显然我们查看hello.txt文件会发现hello world 就躺在里面。
事实上,上面的重定向> 也等价于1> ,即将上述命令echo hello world的标准输出(stdout)重定向到hello.txt 文件中。那么按照这个逻辑,如果我们将1> 改成 2> 会发生什么呢?也就是将上述命令的标准错误输出(stderr)重定向到hello.txt 。
$ echo hello world 2> hello.txt
你一定已经猜到结果了,对,就是没有任何东西。道理很简单,因为前面这个命令是正确的,那么它的标准错误输出(stderr)就是没有内容的, 将空内容重定向到hello.txt 结果也是显而易见的。但是上述命令会在显示器显示hello world,因为我们将上述命令的标准错误输出重定向到hello.txt 并不影响其本身的标准输出,而在上一个例子中,因为我们已经将其标准输出重定向到hello.txt 中了,自然就不会在显示器上再次显示了。
现在我们继续思考,那么既然有1,2两个不同的通道输出,当我们想把2的标准错误输出也重定向到标准输出然后一起写到某个文件,是不是可以直接使用2>1 这种方式呢?很遗憾这样是不行的,这样系统会认为重定向>后的1是一个文件而不是我们希望的文件描述符,如果我们希望将标准错误输出也重定向到标准输出当中,需要使用>& 。具体如下。
$ echo hello world > hello.txt 2>&1
这里需要注意的是需要将2>&1这部分重定向过程放在后面。大概的逻辑是这样的,首先我们需要让程序的标准输出重定向到hello.txt , 即建立从1-->hello.txt的指向关联。然后再去执行从标准错误输出到标准输出1的重定向,即建立从2-->1的指向关联。这样因为1已经关联到hello.txt,那么自然的我们也将2的标准错误输出顺利地写入目标文件中了。
事实上,它还有两种等价的写法
$ echo hello world >& hello.txt
or
$ echo hello world &> hello.txt
1.比如我们可以在command命令前加上>&2 (关于这一点的理解并不保证正确,但是实验结果似乎符合我的想法)
在这种情况下,意味着即使后面的命令即使正确,输出也会变成标准错误输出,意味着原本的标准输出就无了。我们可以用 | grep来进行测试,因为grep会默认从标准输出种进行指定形式的筛选,如果标准输出为空,自然也就无返回结果了。
首先一下是我当前路径下文件的情况
然后我在该dir下执行下面命令
$ >&2 ls | grep log
结果就只是输出了我当前目录的文件。
但是如果我在正常情况下执行(或者使用>&1)
正如预期一样,通过管道函数+grep成功获取到包含log的文件。
2.再比如在command后加上>&2 情况下,意味着将标准输出重定向到标准错误输出中,那么自然原来1通道的输出就没有了,自然| grep也无法进行对应文件的捕捉了。以下是实验结果
这篇文章更多算是自己的一个学习笔记吧,可能在理解和思考上还存在一些问题。如果大家觉得我的理解哪里存在问题的话,欢迎批评指正。
参考:
1.如何理解Linux shell中“2>&1”
2.Linux命令- echo、grep 、重定向、1>&2、2>&1的介绍