参考资料
目录
一. 作用
⏹作用于不接收管道传参的命令,使其接受管道传来的标准输入作为参数
- 我们可以通过
mkdir
命令来创建3个文件夹
mkdir file1 file2 file3
- 但如果通过下面这种方式创建,就会报错,因为
mkdir
不接收管道传参
fengyehong@ubuntu:~$ echo "file1 file2 file3" | mkdir
mkdir: missing operand
Try 'mkdir --help' for more information.
- 我们可以通过
xargs
命令使mkdir
接收管道传来的标准输入,从而成功创建文件夹
fengyehong@ubuntu:~$ ls -l file*
ls: cannot access 'file*': No such file or directory
# 通过 xargs 命令使其而接收管道传参
fengyehong@ubuntu:~$ echo "file1 file2 file3" | xargs mkdir
fengyehong@ubuntu:~$
fengyehong@ubuntu:~$ ls -l file*
file1:
total 0
file2:
total 0
file3:
total 0
二. 基本语法
xargs [-options] [command]
2.1 -d 指定分隔符
- 默认情况下,xargs将空格作为分隔符,把标准输入分解成一个个命令行参数。
- 下面这行明林执行之后,会创建 helloA ~ helloC 的3个文件夹
echo "helloA helloB helloC" | xargs mkdir
- 由于
helloD,helloE,helloF
中并没有空格,因此下面的命令会创建一个名字为helloD,helloE,helloF
的文件夹
echo "helloD,helloE,helloF" | xargs mkdir
⏹可以通过-d
来指定分隔符为,
,从而通过下面的命令创建3个文件夹
tr -d '\n'
:删除hello_3
末尾的换行符
fengyehong@ubuntu:~$ echo "hello_1,hello_2,hello_3" | tr -d '\n' | xargs -d ',' mkdir
fengyehong@ubuntu:~$
fengyehong@ubuntu:~$ ls -l hello*
hello_1:
total 0
hello_2:
total 0
hello_3:
total 0
2.2 -p 与 -t选项
-p
:打印出要执行的命令,询问用户是否要执行。-t
:打印出最终要执行的命令,然后直接执行,不需要用户确认。
fengyehong@ubuntu:~$ echo "helloA helloB helloC" | xargs -p mkdir
mkdir helloA helloB helloC ?...y
2.3 -L 指定多少行作为一个命令行参数
⏹file_suffix.txt
文件中有两行,我们通过xargs
传递给find命令会报错
fengyehong@ubuntu:~/jmw_work_space$ cat file_suffix.txt
*.txt
*.csv
fengyehong@ubuntu:~/jmw_work_space$ cat file_suffix.txt | xargs find -name
find: paths must precede expression: *.csv
Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec|time] [path...] [expression]
⏹可以通过-L
选项,指定每一行作为参数运行find
命令
- 💥注意:
-L
选项通过换行符来控制 -n
:选项通过参数的数量来控制,不考虑换行符
fengyehong@ubuntu:~/jmw_work_space$ cat file_suffix.txt | xargs -L 1 find -name | grep -v 'txt'
./20270720/sftp_data.csv
./20240124/sort3.csv
./work/test-data.csv
./20240102/14/temp/business-content-1.csv
./20240102/14/temp/business-content-2.csv
./20240102/15/temp/business-content-1.csv
./20240102/15/temp/business-content-2.csv
./20240421/newfile.csv
⏹另外一个echo的例子
- 每一行运行一次echo,一共有四行,所以运行了四次echo
- 每两行运行一次echo,一共有两行,所以运行了两次echo
fengyehong@ubuntu:~$ echo -e "你好\n世界\n哈哈\n啊啊" | xargs -L 1 echo
你好
世界
哈哈
啊啊
fengyehong@ubuntu:~$ echo -e "你好\n世界\n哈哈\n啊啊" | xargs -L 2 echo
你好 世界
哈哈 啊啊
- 没有换行符,因此只能打印在一行上
fengyehong@ubuntu:~$ echo "你好 世界 哈哈 啊啊" | xargs -L 2 echo
你好 世界 哈哈 啊啊
2.4 -n 指定将多少项作为参数
- 指定2项作为参数
fengyehong@ubuntu:~$ echo {0..9} | xargs -n 2 echo
0 1
2 3
4 5
6 7
8 9
xargs
默认通过空格分隔,同时指定2项作为参数
fengyehong@ubuntu:~$ echo "你好 世界 哈哈 啊啊" | xargs -n 2 echo
你好 世界
哈哈 啊啊
xargs
指定通过-d
选项指定逗号来进行分隔,同时指定2项作为参数
fengyehong@ubuntu:~$ echo "你好,世界,哈哈,啊啊" | tr -d '\n' | xargs -d ',' -n 2 echo
你好 世界
哈哈 啊啊
2.5 -I 指定命令行参数占位符
⏹如果xargs
要将命令行参数传给多个命令,可以使用-I
。
- 通过下面的命令批量生成
mv
语句 - 其中
{}
只是指定的占位符,也可以是别的符号,例如@
fengyehong@ubuntu:~$ echo -e "file1\nfile2\nfile3" | xargs -I {} echo "mv {} {}.bak"
mv file1 file1.bak
mv file2 file2.bak
mv file3 file3.bak
xargs -I {} sh -c 'echo {}; mkdir {}'
{}
:指定的占位符sh -c
:可以执行通过字符串传递的命令
fengyehong@ubuntu:~$ ls -l file*
ls: cannot access 'file*': No such file or directory
# 批量创建文件夹
fengyehong@ubuntu:~$ echo -e "file1\nfile2\nfile3" | xargs -I {} sh -c 'echo {}; mkdir {}'
file1
file2
file3
fengyehong@ubuntu:~$ ls -l file*
file1:
total 0
file2:
total 0
file3:
total 0
2.6 --max-procs 指定并行进程的数量
⏹待下载的文件
fengyehong@ubuntu:~$ cat download_file_list.txt
https://static.centbrowser.cn/win_stable/5.1.1130.129/centbrowser_5.1.1130.129_x64.exe
https://files2.freedownloadmanager.org/6/latest/fdm_x64_setup.exe
- xargs默认只用一个进程执行命令。
--max-procs
指定同时用多少个进程并行执行命令。--max-procs 3
表示同时最多使用3个进程,--max-procs 0
表示不限制进程数。curl -O
:表示文件下载
⏹我们使用time
命令计算下载所消耗的时间,可以看到设置--max-procs
之后,消耗的时间由 1m4.787s
⇒ 0m32.101s
fengyehong@ubuntu:~$ time cat download_file_list.txt | xargs -I {} curl -O {}
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 136M 100 136M 0 0 3375k 0 0:00:41 0:00:41 --:--:-- 4067k
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 43.0M 100 43.0M 0 0 1897k 0 0:00:23 0:00:23 --:--:-- 2032k
real 1m4.787s
user 0m0.640s
sys 0m5.412s
# 设置 --max-procs=3 ,提高下载并发量
fengyehong@ubuntu:~$ time cat download_file_list.txt | xargs --max-procs=3 -I {} curl -O {}
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--%:-- -- :--:--T --:--:-- 0otal % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 43.0M 100 43.0M 0 0 1915k 0 0:00:23 0:00:23 --:--:-- 2014k
100 136M 100 136M 0 0 4373k 0 0:00:32 0:00:32 --:--:-- 4249k
real 0m32.101s
user 0m0.256s
sys 0m2.868s
三. 小案例
3.1 文件删除
⏹删除当前目录下的所有 .tmp 文件
# 先创建测试文件
touch file_{1..5}.tmp
# 一口气删除
find . -name "*.tmp" | xargs rm
⏹每次最多传递10个文件名, 一次会删除10个文件,如果有50个文件的话,会删除5次,直到把所有的文件都给删除
- 可以使用
-p
,在删除之前提示让用户确认 -n 10
:一次传入10个文件名
# 创建50个测试文件
touch file_{01..50}.tmp
fengyehong@ubuntu:~$ find . -name "*.tmp" | xargs -p -n 10 rm
rm ./file_03.tmp ./file_11.tmp ./file_50.tmp ./file_16.tmp ./file_02.tmp ./file_40.tmp ./file_39.tmp ./file_36.tmp ./file_38.tmp ./file_32.tmp ?...n
rm ./file_10.tmp ./file_12.tmp ./file_45.tmp ./file_01.tmp ./file_14.tmp ./file_09.tmp ./file_05.tmp ./file_35.tmp ./file_07.tmp ./file_33.tmp ?...n
rm ./file_23.tmp ./file_37.tmp ./file_31.tmp ./file_13.tmp ./file_34.tmp ./file_25.tmp ./file_29.tmp ./file_04.tmp ./file_15.tmp ./file_47.tmp ?...n
rm ./file_22.tmp ./file_30.tmp ./file_06.tmp ./file_41.tmp ./file_27.tmp ./file_49.tmp ./file_44.tmp ./file_21.tmp ./file_28.tmp ./file_08.tmp ?...n
rm ./file_19.tmp ./file_18.tmp ./file_43.tmp ./file_46.tmp ./file_17.tmp ./file_20.tmp ./file_24.tmp ./file_42.tmp ./file_48.tmp ./file_26.tmp ?...n
3.2 文件打包
⏹找到的文件进行打包
find . -name "*.txt" | xargs -p tar -cvf archive.tar
3.3 文件移动
⏹找到的文件批量移动
- 如果目标文件太多并且体积过大,可能会导致性能问题
# 创建50个测试文件
touch file_{01..50}.tmp
# 将找到的目标文件全部移动
find . -type f | xargs mv -t ~/dst
⏹找到的文件批量移动,一次移动5个文件,并将执行的命令输出
-L 5
:每次传递 5 个文件给 mv命令,分批执行。
对于大量文件,这可以防止单次传递过多文件导致问题。xargs -t
:将要执行的命令打印到控制台上
# 创建50个测试文件
fengyehong@ubuntu:~$ touch file_{01..50}.tmp
# 一次移动5个文件
fengyehong@ubuntu:~$ find . -type f -name "*.tmp" | xargs -t -L 5 mv -t ~/dst
mv -t /home/fengyehong/dst ./file_03.tmp ./file_11.tmp ./file_50.tmp ./file_16.tmp ./file_02.tmp
mv -t /home/fengyehong/dst ./file_40.tmp ./file_39.tmp ./file_36.tmp ./file_38.tmp ./file_32.tmp
mv -t /home/fengyehong/dst ./file_10.tmp ./file_12.tmp ./file_45.tmp ./file_01.tmp ./file_14.tmp
mv -t /home/fengyehong/dst ./file_09.tmp ./file_05.tmp ./file_35.tmp ./file_07.tmp ./file_33.tmp
mv -t /home/fengyehong/dst ./file_23.tmp ./file_37.tmp ./file_31.tmp ./file_13.tmp ./file_34.tmp
mv -t /home/fengyehong/dst ./file_25.tmp ./file_29.tmp ./file_04.tmp ./file_15.tmp ./file_47.tmp
mv -t /home/fengyehong/dst ./file_22.tmp ./file_30.tmp ./file_06.tmp ./file_41.tmp ./file_27.tmp
mv -t /home/fengyehong/dst ./file_49.tmp ./file_44.tmp ./file_21.tmp ./file_28.tmp ./file_08.tmp
mv -t /home/fengyehong/dst ./file_19.tmp ./file_18.tmp ./file_43.tmp ./file_46.tmp ./file_17.tmp
mv -t /home/fengyehong/dst ./file_20.tmp ./file_24.tmp ./file_42.tmp ./file_48.tmp ./file_26.tmp
3.4 其他命令结合复杂用法
⏹下面的命令的详细拆解,参考这篇博客 ⇒ Linux grep技巧 结合awk查询
$ grep -a "PMT.payinfoforprc.test.search" ./file*.log | \
> grep -a "oldest_data_search=1" | \
> awk '{print $1}' | \
> awk -F ":" '{print "^"$2 " " $1}' | \
> xargs -L 1 grep -a | \
> grep -E "MYCODE2005