对话 UNIX: 掌握强大的命令行( 二 )


更改进程数据的源和目标被称为重定向 。您可重定向 stdin 以从文件或其他源读取数据,还可分别对 stdout 和 stderr 重定向以将数据写到终端窗口之外的其他位置 。在许多情况下,如前面所列出的初始 find 命令中,您还可重定向实用工具以从其他工具接收和为它们产生所需的数据 。这就是管道 (|) 的用途 。您可在命令中通过管道来生成进程链路,即将某条命令的数据发送到下一条命令,这类似于通过铜管将水从热水器传输到洗手池中 。
图 4 所示为 find . -type f -print | sort | uniq 命令的示意图 。
图 4. 通过管道进行链接的三个实用工具的示意图
find 命令的 stdout 成为 uniq stdin,然后 uniq 的 stdout 又成为 sort 的 stdin 。最后,sort 将结果打印到其标准输出设备,即所连接的终端窗口上 。这些命令的 stderr 未进行重定向,因此所有三个实用工具都会将错误消息打印到终端上 。(来自三个实用工具的错误消息会混在一起,但保持正确的顺序 。)
如有需要,您可进一步扩展管道,将 uniq 的输出重定向到另外的实用工具 。这只需使用另一个管道即可对转换进行扩展 。例如,您可在命令之后附加 | less 以使用 less 对输出结果进行分页,或者您可添加 | wc -l 以统计独特文件名的数目 。(wc 为 Word count 的首字母缩写,wc 可统计字符、单词和行数 。)
此外,您还可使用 > 来将整个命令序列的输出结果保存到一个文件中(这将覆盖现有的文件内容) 。您可使用 >> 以将命令输出结果附加 到现有文件之后(如果文件不存在,则创建新文件) 。
另一个有用的重定向是 < 。图 5 所示为如何重定向 stdin 以从文件中进行读取 。命令 sort 从指定文件中读取单词列表并按字母顺序进行排序 。
图 5. 重定向标准输入以读取文件内容
您常常会需要捕获 stdout 和 stderr 。例如,如果您正在运行大型的数据挖掘任务,则可能要检查执行过程中的中间输出以及可能出现的任何错误 。您可使用重定向语法的一些变种来实现该功能:|&, >&, >>& 可分别对 stdout 和 stderr 实现管道、创建、附加功能 。图 6 所示为如何将 stdout 和 stderr 合并到单一的输出流 。
图 6. 合并标准输出和标准错误设备
Z shell 介绍
包括 Bourne shell (bash) 和 Korn shell (ksh) 在内的多数现代 Unix shell 都支持这里提到的重定向功能,尽管在这些 shell 中具体语法可能存在细微差别 。(请查看您的 shell 文档以了解详细信息) 。
重定向中的多数操作符在所有的 Unix shell 中已经连续使用了至少 25 年 。但是,多数 shell 并没有提供新的特性或采用新方式来应用重定向 。例如,多数 shell 只能将输入重定向到单个文件,因此您必须使用如 tee 等实用工具来输出到多个目标 。(类似于水管工人使用的 T 型管 (Tee),tee 只支持单个或两个输出 。)这里提供一个使用 bash 作为 shell(命令行解释器)的示例:
清单 5. bash 示例
bash$ ls
tellme
bash$ cat tellme
echo Your current login, working Directory, and system are...
whoami
pwd
systemname
bash$ bash < tellme |& tee log
Your current login and working directory are...
strike
/home/strike
bash: systemname: command not found
bash$ ls
tellme log
bash$ cat log
Your current login and working directory are
strike
/home/strike
bash: systemname: command not found
尽管 UNIX shell 具有较高的专用性,且通常使用键盘进行交互,但某些 shell 如 bash 等也能从文件读取输入内容 。(实际上,stdin 也是一种文件 。)在前面的片段中,短语 bash < commands 告诉 bash 执行在文件 tellme 中找到的命令列表 。短语 |&tee log 将 bash 的 stdout 和 stderrto 通过管道重定向到 tee 实用工具,后者将其 stdin 打印到 stdout 和 文件 log 中 。

推荐阅读