要了解重定向和管道的规则,我们需要引入一个前文并未引入的概念。绝大部分 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]。