重定向和管道

关于进程的一些补充

要了解重定向和管道的规则,我们需要引入一个前文并未引入的概念。绝大部分 UNIX® 进程(包括图形应用程序,但不包括绝大多数守护程序)至少使用三个文件描述符:标准输入、标准输出和标准错误输出。它们相应的序号是 0、1 和 2。一般来说,这三个描述符与该进程启动的终端相关联,其中输入为键盘。重定向和管道的目的是重定向这些描述符。本节中的实例将帮助您更好地了解这些概念。

重定向

假设您想要一张 images 目录中所有以 .png 结尾的文件[6]列表。该列表非常长,因此您会想把它先放到一个文件中,然后在有空的时候查看。您可以输入下述命令:

$ ls images/*.png 1>file_list

这表示把该命令的标准输出(1)重定向到(>)file_list 文件。其中的 > 操作符是输出重定向符。如果要重定向到的文件不存在,它将被创建;不过如果它已经存在,那么它先前的内容将被覆盖。不过,该操作符默认的描述符就是标准输出,因此就不用在命令行上特意指出。所以,上述命令可以简化为:

$ ls images/*.png >file_list

其结果是一样的。然后您就可以用某个文本文件查看器(比如 less)来查看。

现在,假定您想要知道这样的文件有多少。不用手工计数,您可以使用 wc (单词计数(Word Count))这个工具。使用其 -l 选项将在标准输出上显示文件的行数。所以,您可以:

wc -l 0<file_list

就可以得到期望的结果。其中的 < 操作符是输入重定向符,并且其默认重定向描述符是标准输入(即 0)。因此您只需:

wc -l <file_list

假定您又想去掉其中所有文件的“扩展名”,并将结果保存到另一个文件。要完成这一功能可以使用 sed (流编辑器(Stream EDitor))。您只要将 sed 的标准输入重定向为 file_list,并将其输出重定向到结果文件 the_list

sed -e 's/\.png$//g' <file_list >the_list

您所需要的就已被创建,并等待您在有空的时候用任何查看器查看。

重定向标准错误输出也很有用。例如:您会想要知道在 /shared 中有哪些目录您不能够访问。一个办法是递归地列出该目录并重定向错误输出到某个文件,并且不要显示标准输出:

ls -R /shared >/dev/null 2>errors

这表示标准输出将被重定向到(>)/dev/null(所有输出到此特殊文件的东西都将被丢弃,即不显示标准输出),并将标准错误输出(2)重定向到(>)errors 文件。

管道

管道在某种程度上是输入和输出重定向的结合。其原理同物理管道类似:一个进程向管道的一端发送数据,而另一个进程从该管道的另一端读取数据。管道符是 |。让我们再来看看上述文件列表的例子。假设您想直接找出有多少对应的文件,而不想先将它们保存到一个临时文件,您可以:

ls images/*.png | wc -l

这表示将 ls 命令的标准输出(即文件列表)重定向到 wc 命令的输入。这样您就直接得到了想要的结果。

您也可以使用下述命令得到“除去扩展名”的文件列表:

ls images/*.png | sed -e 's/\.png$//g' >the_list

或者,如果您想要直接查看结果而不想保存到某个文件:

ls images/*.png | sed -e 's/\.png$//g' | less

管道和重定向不仅仅只能用于人类可以阅读的文本文件。例如下述来自 终端 的命令:

xwd -root | convert - ~/my_desktop.png

将把您桌面的截屏保存到您个人目录中的 my_desktop.png 文件[7]



[6] 您可能会觉得奇怪:为什么不直接说“PNG 图片”,而要说“.png 结尾的文件”呢?再提醒一次,在 UNIX® 下的扩展名惯例是:扩展名并不表示文件的类型。以 .png 结尾的文件很可能是一个 JPEG 图像、一个应用程序、一个文本文件或者任何什么别的类型的文件。在 Windows® 下也一样!

[7] 它确实会是一个 PNG 图片(不过您需要事先安装了 ImageMagick 应用程序包)。