到目前为止,我们都是单独使用命令行。然而有些命令的强大之处在于将现有单个命令结合起来从而达到用户想要的结果。
通常情况下命令都是将结果输出到屏幕上,但也有其他一些灵活的选项。一种是我们刚刚讲述过的输出重定向>,另外一种方法是piping。一个pipe就是一个连接器,将命令1的输出作为命令2的输入。
两个常用的命令ps和grep我们之前已经将过,前者是列出进程,后者是查找字符串匹配。现在我们将这个两个命令结合起来,查找现在哪些用户在运行Nethack。命令如下:
ps aux | grep nethack
这条命令首先创建了一个目前正在运行的所有进程的list,并且把这个list输出给grep命令,grep命令排除掉所有与nethack不匹配的进程。Ubuntu允许用户pipe尽可能多的命令。例如我们可以加入wc命令,该命令计算它的输入的行数,字数和字符个数。Pipe上这个命令可以精确的计算出nethack被运行了多少次。命令如下:
ps aux | grep nethack | wc -l
-l参数(小写的L)告诉wc命令只计算输出行数。
用这种方法pipe多个命令比使用find命令配上-exec参数更受人欢迎。因为find命令的灵活多变让许多用户望而止步。这里就有一个非常好用的xargs命令,xargs命令的作用是把命令1的输出作为命令2的参数。
这里举个简单的例子。以下这条命令我们之前见过:
find / -name "*.txt" -size +10k -user cindy -not -perm +o=r-exec chmod o+r {} \;
这条命令从目录/开始搜索名字匹配*.txt,大小大于10KB,被用户cindy拥有,对于其他用户没有读权限的文件。然后对这些搜索到的文件执行chmod命令。这是一条很复杂的命令,不熟悉find命令的人理解起来可能非常困难。
因此我们可以把这条命令分为两个命令:find命令和xargs命令。常见的使用方法是:
find / -name "*.txt" -size +10k -user cindy -not -perm +0=r |xargs chmod o+r
这样就删除了经常造成困惑和错误的{} \;,而且实现同样的功能,而且更快。为啥这条命令会比之前的命令更快呢?这是因为加上-exec的find命令实际上是对每个搜索到的文件调用chmod命令。而xargs命令不同的是,它先调用find查找到所有满足条件的文件,作为chmod的输入(因为chmod支持输入为多个文件),因此chmod只调用了一次。也就是说xargs这里的工作方式有点类似于以下命令:
xargs chmod o+r file1.txt file2.txt file3.txt file4.txt
但是并不是每个命令都能接受多个文件作为输入的。所以你可以对xargs命令加上-l参数,xargs会执行这个命令的时候,将每一行作为命令的输入。如果你想要明确你的操作,加上-p参数,xargs会在执行每一条命令前提示你。
你可以通过使用-i命令指定匹配到的行应该被放在你命令的什么位置。这个参数很重要,比如当你并不是准备把匹配到的行放在命令的最后位置,或者需要它在命令中的多个位置出现时。使用-i参数时自动启用-l参数的功能,每一行都被单独送到命令的输入中。例如,下面这条命令是查找目录/home/cindy下所有大于10,000KB(10MB)的文件,并把这些文件复制到/home/cindy/archive目录下:
find /home/cindy -size +10000k | xargs -i cp {} /home/cindy/archive
xargs和find的结合使用是一个特例。更多情况下,人们使用pipe是因为命令1的输出正好作为命令2的输入。下面有两个例子:
ps aux --sort=-%cpu | grep -v 'whoami'
ps -N ux --sort=-%cpu
第1条命令是输出所有用户的所有进程,并将结果传递给grep,grep排除掉匹配程序whoami的输出(our username)的结果。也就是说,第1条命令将会输出所有被其他用户运行的进程,按照cpu使用情况排序。第2条命令实现相同的效果。