基本使用
xargs
是 Linux 系统中的一个命令行工具,它可以读取标准输入并将其作为参数构建新的命令并执行。xargs
可以帮助 echo
、rm
、mkdir
等命令接收标准输入作为参数。
1 | xargs mkdir |
比如执行 xargs mkdir
命令,输入 test1 test2
后回车,再按 CTRL-D
结束输入,等效于直接执行 mkdir test1 test2
命令。
即 xarg
读取了标准输入中的 test1 test2
,并将它们作为参数传递给 mkdir
命令,组合成一个完整的 mkdir test1 test2
命令并执行。
实际上 xargs
很少用在上述交互式场景中,更多的是搭配管道符 |
,通过前一个命令的输出构建新的命令。
1 | echo test3 test4 test5 | xargs mkdir |
|
和 | xargs
的区别:
- 管道符
|
是将左边命令的输出结果作为右边命令的输入值 | xargs
则可以将左边命令的输出结果作为右边命令的参数选项
find 与 xargs
xargs
最常见的搭配应该就是 find
命令了。即通过 find
查找特定的文件或目录,再将结果传递给 xargs
,对找到的结果执行特定的操作。
如删除 /tmp
路径下最近两周内未做改动的文件:find /tmp -type f -mtime +14 | xargs rm
有一点特别需要注意:默认情况下,xargs
从标准输入读取命令参数时,会以空格作为分隔符来识别多个选项。
而文件和目录的名字有时候也会包含空格,导致一个文件名被 xargs
识别为两个参数。
1 | mkdir test\ 6 |
更安全一点的做法是使用 -0
选项。-0
选项可以指定 xargs
在读取标准输入时使用 null
作为分隔符。而 find
命令的 -print0
选项同样可以将输出指定为使用 null
进行分割。
即将前面的命令替换为 find . -type d -print0 | xargs -0 rmdir
。
find 搭配 -exec
选项和搭配 xargs 命令的区别
find
命令可以使用其 -exec
选项对查找到的结果执行特定的操作。同样的需求 xargs
也可以实现。
比如需要删除当前目录下所有的 TXT 文件:
- 使用
-exec
:find . -type f -name "*.txt" -exec rm {} \;
- 使用
xargs
:find . -type f -name "*.txt" | xargs rm
实际上两者的执行效率存在着很大的差距。
比如使用 for i in {1..100}; do touch $i.txt; done
命令创建 100 个 TXT 文件,再分别使用上述两个命令删除这些文件(用 time
命令计时),具体的效率如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 for i in {1..100}; do touch $i.txt; done
ls
1.txt 18.txt 27.txt 36.txt 45.txt 54.txt 63.txt 72.txt 81.txt 90.txt
10.txt 19.txt 28.txt 37.txt 46.txt 55.txt 64.txt 73.txt 82.txt 91.txt
100.txt 2.txt 29.txt 38.txt 47.txt 56.txt 65.txt 74.txt 83.txt 92.txt
11.txt 20.txt 3.txt 39.txt 48.txt 57.txt 66.txt 75.txt 84.txt 93.txt
12.txt 21.txt 30.txt 4.txt 49.txt 58.txt 67.txt 76.txt 85.txt 94.txt
13.txt 22.txt 31.txt 40.txt 5.txt 59.txt 68.txt 77.txt 86.txt 95.txt
14.txt 23.txt 32.txt 41.txt 50.txt 6.txt 69.txt 78.txt 87.txt 96.txt
15.txt 24.txt 33.txt 42.txt 51.txt 60.txt 7.txt 79.txt 88.txt 97.txt
16.txt 25.txt 34.txt 43.txt 52.txt 61.txt 70.txt 8.txt 89.txt 98.txt
17.txt 26.txt 35.txt 44.txt 53.txt 62.txt 71.txt 80.txt 9.txt 99.txt
time find . -type f -name "*.txt" -exec rm {} \;
find . -type f -name "*.txt" -exec rm {} \; 0.05s user 0.02s system 104% cpu 0.060 total
for i in {1..100}; do touch $i.txt; done
time find . -type f -name "*.txt" | xargs rm
find . -type f -name "*.txt" 0.00s user 0.00s system 80% cpu 0.001 total
xargs rm 0.00s user 0.00s system 94% cpu 0.003 total
前者是 0.06,后者是 0.004。使用 xargs
的执行效率更高。
输出执行的命令
-t
选项可以把 xargs
拼接后执行的命令打印到终端窗口中。方便对脚本进行调试。1
2 echo test1 test2 test3 | xargs -t mkdir
mkdir test1 test2 test3
输出命令并提示用户确认
-p
选项可以把 xargs
拼接后执行的命令打印出来,并等待用户进行确认。1
2 ls | xargs -p rmdir
rmdir test1 test2 test3 ?...y
执行多个命令
借助 -I
选项可以令 xargs
同时执行多个命令。1
2
3
4
5
6
7
8
9
10 cat foo.txt
one
two
three
cat foo.txt | xargs -I % sh -c 'echo %; mkdir %'
one
two
three
ls
foo.txt one three two
常用实例
查找当前路径下所有的 PNG 图片并将它们归档到 images.tar.gz
压缩包中:$ find . -name "*.png" -type f -print0 | xargs -0 tar -cvzf images.tar.gz
获取当前系统中所有用户的用户名,以单行列表的形式输出:1
2 cut -d: -f1 < /etc/passwd | sort | xargs echo
_apt backup bin daemon games gnats irc landscape list lp mail man messagebus news nobody pollinate postgres proxy root sshd starky sync sys syslog systemd-network systemd-resolve systemd-timesync tcpdump tss uucp uuidd www-data
删除当前路径下名为 no_use
的文件:$ find . -name "no_use" -type f -print0 | xargs -0 rm -v -f
复制一个文件到多个路径下:1
2
3
4
5 ls
dest1 dest2 test_file
echo ./dest1/ ./dest2/ | xargs -n 1 cp -v ./test_file
'./test_file' -> './dest1/test_file'
'./test_file' -> './dest2/test_file'
上面例子中 xargs
的 -n 1
选项非常重要。-n
选项用于指定 xargs
在将标准输入作为参数与命令拼接在一起时,参数的最大长度。
简单来说,当 -n
为 1 时,标准输入中以空格分割的每一项都与命令进行拼接,最终形成多条命令;当不存在 -n 1
时,标准输入中以空格分割的所有参数项直接与命令进行拼接,形成一条命令并执行。1
2
3
4
5
6 echo ./dest1/ ./dest2/ | xargs -n 1 -t cp ./test_file
cp ./test_file ./dest1/
cp ./test_file ./dest2/
echo ./dest1/ ./dest2/ | xargs -t cp ./test_file
cp ./test_file ./dest1/ ./dest2/
cp: -r not specified; omitting directory './dest1/'
echo ./dest1/ ./dest2/ | xargs -n 1 cp ./test_file
等效于cp ./test_file ./dest1/
和cp ./test_file ./dest2/
两条命令echo ./dest1/ ./dest2/ | xargs cp ./test_file
等效于cp ./test_file ./dest1/ ./dest2/
一条命令(语法是错的)
参考资料
Linux and Unix xargs command tutorial with examples
12 Practical Examples of Linux Xargs Command for Beginners