Linux xargs命令

参考资料

  1. 阮一峰 - xargs 命令教程
  2. xargs コマンド

目录

  • 一. 作用
  • 二. 基本语法
    • 2.1 -d 指定分隔符
    • 2.2 -p 与 -t选项
    • 2.3 -L 指定多少行作为一个命令行参数
    • 2.4 -n 指定将多少项作为参数
    • 2.5 -I 指定命令行参数占位符
    • 2.6 --max-procs 指定并行进程的数量
  • 三. 小案例
    • 3.1 文件删除
    • 3.2 文件打包
    • 3.3 文件移动
    • 3.4 其他命令结合复杂用法


一. 作用

⏹作用于不接收管道传参的命令,使其接受管道传来的标准输入作为参数

  • 我们可以通过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.787s0m32.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

你可能感兴趣的:(Linux,linux)