《Linux Shell 脚本攻略(第 2 版)》读书笔记
- xargs 应该紧跟在管道操作符之后,以标准输入作为主要的源数据流。
- xargs 命令把从 stdin 接收到的数据重新格式化,再将其作为参数提供给其他命令。
实战演练
- 将多行输入转换成单行输出。
$ cat example.txt # 样例文件
1 2 3 4 5 6
7 8 9 10
11 12
$ cat example.txt | xargs
1 2 3 4 5 6 7 8 9 10 11 12
- 将单行输入转换成多行输出。
$ cat example.txt | xargs -n 3 # 指定每行最大的参数数量n
1 2 3
4 5 6
7 8 9
10 11 12
- 为输入指定一个定制的定界符。
$ echo "splitXsplitXsplitXsplit" | xargs -d X # 指定 X 为定界符
split split split split
~注意,OS X 系统中的 xargs 没有 -d 选项。~
补充内容
1. 读取 stdin,将格式化参数传递给命令
我们有一个文件。现在,需要对文件的内容进行处理,文件的内容如下:
$ cat args.txt
arg1
arg2
arg3
每次处理一个参数
$ cat args.txt | xargs -n 1 echo
arg1
arg2
arg3
一次性提供所有参数
$ cat args.txt | xargs echo
arg1 arg2 arg3
为处理每个数据提供统一的固定内容
$ cat args.txt | xargs -I {} echo hello {} -l
hello arg1 -l
hello arg2 -l
hello arg3 -l
-I {}
指定了替换字符串。对于每一个命令参数,字符串 {} 都会被从 stdin 读取到的参数替换掉。
使用
-I
的时候,命令以循环的方式执行。如果有 3 个参数,那么命令就会连同{}一起被执行 3 次。在每一次执行中{}都会被替换为相应的参数。
2. 结合 find 使用 xargs
错误的使用方式
$ find . -type f -name "*.txt" -print | xargs rm -f
# 删除本目录下的所有 .txt 文件
这么做很危险。有时候可能会删除不必要的文件。比如文件名中出现定界符('\n'或' ')。
正确的使用方式
只要我们把 find
的输出作为 xages
的输入,就必须将 -print0
与 find
结合使用,以字符 null(\0)
来分隔输出。
$ find . -type f -name "*.txt" -print0 | xargs -0 rm -f
# 删除本目录下的所有 .txt 文件
3. 统计源代码目录中所有 C 程序文件的行数
$ find . -type f -name "*.c" -print0 | xargs -0 wc -l
# wc 是一个统计文件里面有多少单词,多少行,多少字符的工具
如果项获得有关个人源代码更多的统计信息,可以使用 SLOCCount 工具。
4. 结合 stdin,巧妙运用 while 语句和子 shell
$ cat args.txt | ( while read arg; do echo $arg; done )
# 等同于 cat args.txt | xargs -I {} echo hello {}
在 while
循环中,可以将 echo $arg
替换成任意数量的命令,这样我们就可以对同一个参数执行多条命令。