Linux:xargs命令
学习自:
如何在Linux上使用xargs命令(非常详细)零基础入门到精通,收藏这一篇就够了-CSDN博客
1、前言
xargs的作用:将一个命令的输出,转化为参数传给另一个命令。
例如,我们可以通过如下指令,实现统计目录/data下各个文件的行数、单词数、字符数的目的:
for i in $(ls) do wc $i done
实际上就是把ls指令的每行都作为wc的参数执行一遍wc。
而通过xargs,我们可以直接把ls的结果作为参数传给wc,来实现相同的目的:
ls | xargs wc 5795 72282 447054 redis_6379.log 38 485 3849 sentinel.log
但是如果我们不用wc,就会出现下边这种情况:
ls . | wc 3 3 39 #这里是把ls的结果当做一个整体进行统计了,有3行、3个单词、39个字符
更规范的说法是:在Linux中,所有标准应用程序都有与之关联的三个数据流:标准输入stdin、标准输出stdout、标准错误stderr。
Linux的一大功能是可以将一个命令的标准输出流通过管道等方式传递给另一个命令的标准输出流。但是并不是所有指令都接受另一个命令的标准输出作为它的标准输入,例如上文的wc,以及echo、rm、mkdir等命令。
需要用xargs处理的常见命令
wc、echo、kill、rm、mkdir
而xargs可以解决这个问题,它就是一个使用标准数据流构建管道的命令。通过xargs可以使上述命令接受标准输入作为其参数。
xargs接受管道输入,也接受来自文件的输入。
xargs使用该输入作为我们指定的命令参数。如果我们没有给xargs指定特定接收命令,则默认使用echo。xargs始终生成单行输出,即使输入的数据是多行的:
由于xargs后没跟其他命令时,会默认跟echo,所以我们可以看出来xargs确实把ls -1的结果作为参数传给了其他命令。
2、配合wc命令使用xargs
回到一开始的例子:wc,统计文件行数、字母数、字符数
ls -1 | xargs wc 5795 72282 447054 redis_6379.log 38 485 3849 sentinel.log 4 8 30 test.shell 5837 72775 450933 总用量
命令运行结果显示了每个文件的统计信息及总数。
这条命令执行了以下操作:
- ls列出了所有文件,并将其传给了xargs;
- xargs将所有的文件名传给wc;
- wc将这些文件名作为命令行参数进行处理。
3、交互式xargs
xargs允许使用选项-p来让操作者选择是否进行下一步:
这里我们用xargs touch创建3个文件:
echo "one two three" | xargs -p touch touch one two three ?...y
中间出现了文件创建的确认提示,只有输入y或Y时才会执行。
之后我们用ls检查文件是否创建,显示已经创建:
ls one redis_6379.log sentinel.log test.shell three two
4、一次执行多条指令:-I
在上述例子中,我们用xargs只是一次执行一条指令,如echo、wc、touch之类的。
如果要用前边的标准输入作为参数,一次先后执行echo、mkdir指令,该如何实现?
答案是-I选项。
xargs的-I选项的本质是inplace,即字符串替换。将后边任何出现占位字符串的地方,都替换为传递给xargs的值。
例子:在directories.txt这个文件中,写了一些要创建的目录名称。
cat directories.txt dir_one dir_two dir_three dir_four
目的:创建这些目录,同时输出目录名
cat directories.txt | xargs -I % sh -c 'echo %; mkdir %' dir_one dir_two dir_three dir_four
该指令执行了如下操作:
- cat directories.txt:将directories.txt的内容传给xargs;
- xargs -I %:定义占位字符串 %,后续会把%替换为xargs获得的传入内容;
- sh -c 'echo %; mkdir %':先用上述传入的目录内容替换%,随后执行echo和mkdir指令。
其实可以看出来,所谓执行多个指令,实际上是通过sh -c 和 xargs -I占位替换共同实现的。只要把多个要执行的指令放到sh -c后即可。
用tree -d检查执行结果,进行验证。
tree -d
.
├── dir_four
├── dir_one
├── dir_three
└── dir_two
5、将输入进行拆分,一次取其中的若干条作为参数:-n
在之前的例子中,我们是把整个输入全部作为了xargs后的指令参数来让指令运行的。
例如:ls | xargs wc,实际上可以理解为:
wc redis_6379.log sentinel.log test.shell 或 wc redis_6379.log wc sentinel.log wc test.shell
对于wc、mkdir、echo等允许一次传入多个参数指令而言,这两种写法没啥差别。
但有些指令一次只接受传入一个参数,如cp:
#正确 cp a.txt /tmp cp a.txt /usr #错误 cp a.txt /tmp /usr
此时我们就必须分别执行cp /tmp和cp /usr。
假设/tmp /usr是用echo输出过来的,那么如何实现上述目的?
答案是用-n选项:
-n 一次只取传进来的参数中的n个参与指令运行
因此上述目的可以用如下指令实现:
上述命令中,用cp的参数-v显示复制的详细信息。
用xargs的参数-n 1,一次只取输入进来的参数中的一个,即先把/tmp执行完毕,再执行/usr。