关于Linux Shell 的重定向问题小总结

前言

最近在学习MIT 的一门课叫做6.NULL,在exercise部分看到一个>&2 表示符,作为小白的我又懵逼了,这是个什么意思呢?在一顿搜索之后,才知道这是一种特别的重定向,下面结合别人的讲述以及自己的理解,来做个总结,有不对的地方也希望读者朋友们积极批评指正。

文件描述符0,1,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的介绍

你可能感兴趣的:(Shell,linux,shell)