在使用 Linux 时,你是否遇到过需要将一些命令串在一起,但是其中一个命令不接受管道输入的情况呢?在这种情况下,我们就可以使用 xargs 命令。xargs 可以将一个命令的输出作为参数发送给另一个命令。
在 Linux 中,所有标准的应用程序都有与之关联的三个数据流。分别是标准输入流(stdin),标准输出流(stdout)和标准错误流(stderr)。这些流通过文本来运行,我们使用文本将输入(stdin)发送到命令,然后响应(stdout)将会以文本形式显示在终端窗口上。错误消息也以文本的形式显示在终端窗口上(stderr)。
Linux 和类 Unix 操作系统的一大功能是可以将一个命令的标准输出流传递到另一个命令的标准输入流。第一个命令不会管它的输出是否写到了终端窗口,第二个命令也不会管它的输入是否来自键盘。
虽然所有 Linux 命令都有三个标准流,但是并不是所有命令都接受另一个命令的标准输出作为它的标准输入流的输入。因此我们无法通过管道将输入传给这些命令。
xargs是一个使用标准数据流构建执行管道的命令。通过使用xargs命令我们可以使 echo,rm 和 mkdir 等命令接受标准输入作为它们的参数。
xargs命令
xargs接受管道输入,也可以接受来自文件的输入。xargs 使用该输入作为我们指定的命令的参数。如果我们没有给xargs指定特定的命令,则默认使用 echo。xargs 始终生成单行输出,即使输入的数据是多行的。
假如我们使用 ls 的 -1(每行列出一个文件)选项,则会得到一列文件名称:
$ ls -1 ./*.sh
这一命令列出了当前目录中的 Shell 脚本文件。
如果我们将输出结果通过管道传递给 xargs ,会得到什么样的效果?
$ ls -1 ./*.sh | xargs
可以看出来,输出以一长串文本的形式写到了终端上。由此可见,xargs 可以将输出作为参数传递给其他命令。
配合wc命令使用xargs
我们可以使用 xargs 命令轻松地让 wc 命令计算多个文件中的单词数,字符数和行数
$ ls *.c | xargs wc
执行结果如下:
命令运行结果显示了每个文件的统计信息以及总数。
这条命令执行了以下操作:
ls列出了所有的 .page 文件,并将该列表传给了xargs。
xargs 将所有文件名传递给 wc。
wc 将这些文件名作为命令行参数进行处理。
使用带有确认消息的xargs
我们可以使用 -p(交互)选项来让 xargs 提示我们是否要进行下一步的操作。
如果我们通过 xargs 将一串文件名的字符串传递给 touch 命令,touch 将创建这些文件。
$ echo 'one two three' | xargs -p touch
终端上显示将要执行的命令,xargs 等待我们输入 y 或 Y ,n 或 N 并按 Enter 来响应。如果只按了 Enter ,则视为 n。只有当我们当输入 y 或 Y 时才执行该命令。
我们按下y和 Enter ,然后使用ls用来检查文件是否已经创建。
$ ls one two three
将xargs与多个命令一起使用
我们可以用-I(初始参数)选项来将 xargs 和多个命令一起使用。这一选项定义了替换字符串。在命令行中的任何出现替换字符串的位置,都会插入我们提供给 xargs 的值 。
有点抽象,我们以一个实例来进行讲解。
我们先用 tree 命令查看当前目录中的子目录。该 -d(directory)选项使 tree 命令忽略文件,只输出目录。
$ tree -d
现在只有一个子目录 images 。
在 directories.txt 这个文件中,我们有一些想要创建的目录的名称。我们先用 cat 查看其中的内容。
$ cat directories.txt
我们把这些内容作为输入数据传给 xargs ,执行以下的命令:
$ cat directories.txt | xargs -I % sh -c 'echo %; mkdir %'
这条命令执行了以下操作:
cat directories.txt :将 directrories.txt 文件的内容(所有要创建的目录名称)传给 xargs。
xargs -I % :定义了替换字符串 %。
sh -c:启动一个新的子shell。-c(commond)让 shell 读取命令。
'echo %; mkdir %':每个%都会被替换为 xargs 传过来的目录名称 。echo 命令打印目录名称,mkdir 命令创建目录。
命令执行结果:
我们可以用 tree 验证已创建是否已创建了目录。