[ 知识是人生的灯塔,只有不断学习,才能照亮前行的道路 ]
0x01 前言简述
描述:上一章,我们学习了Linux中查找搜寻文件或目录的相关命令,此章我们学习常常与find命令联合使用,以及在Shell脚本中常用的参数替换 xargs 命令进行实践学习,从而实现更加强大的参数传递和多进程并行执行Linux命令或脚本等
原文地址:Linux 命令:每日一学,参数传递之xargs命令实践
此 Linux 命令 | 系列
文章将作为《#运维从业必学》专栏辅助学习知识,这是也是每位Linux运维工程师必须掌握的基础知识,作者耗费心力、时间进行总结,希望对大家有所帮助,所以若有帮助还请多多关注作者,并鼓励作者创造更多实践文章吧。
好了,还是实践出真知!
0x02 参数替换
xargs 命令 - 将标准输入中的数据转换为命令行参数
描述:xargs(eXtended ARGuments
)工具是给命令传递参数的一个过滤器,也是组合多个命令的一个工具。
由于很多命令不支持|管道来传递参数,此时就需要 xargs 命令的帮助,它可以读入stdin 的数据,并将格式化(空格符、回车符进行分隔)后的数据作为命令的参数,还可以将单行或多行文本输入转换为其他格式,例如,多行变单行以及单行变多行,后续实践我们会介绍到。
另外,许多命令不能接受过多的参数而导致命令执行失败,此时可以使用xargs 命令解决该问题。例如,使用 rm 命令删除百万级文件时会提示参数过多,这时可使用 find
命令 或 ls
命令 与 xargs
命令联用进行删除。。
工具功能:
将管道或标准输入(stdin)数据转换成命令行参数,也能够从文件的输出中读取数据。
将单行或多行文本输入转换为其他格式,例如多行变单行,单行变多行。
默认命令是echo 意味着通过管道传递给 xargs 的输入将会包含换行和空白,不过通过 xargs 的处理,换行和空白将被空格取代。
它能够捕获一个命令的输出,然后传递给另外一个命令,
语法参数:
# 用法
command | xargs [OPTION]... COMMAND [INITIAL-ARGS]..
# 常用参数
-0 # 将NULL作为定界符。
-t # 表示先打印命令,然后再执行。
-a FILE # 指定一个参数文件,而不是从标准输入中读取。
-n NUM # 指定每行显示多少NUM列;
-L num # 从标准输入一次读取 num 行送给 command 命令。
-l # 类似于-L,但如果未指定MAX-LINES,则默认为最多一个非空白输入行
-d '定界字符': # 指定一个定界符注意必须是单字符;
-x, --exit # 如果超过大小(参见-s),则退出。
-r no-run-if-empty # 当xargs的输入为空的时候则停止xargs,不用再去执行了。
-I R # 指定一个替换字符串{},这个字符串再xargs扩展时会被替换掉,当-I与xargx联合使用的时候每一个参数命令都会被执行一次,类似于find的-ok/-exec选项
-i, --replace[=R] # 看linux支持了,将xargs的每项名称,一般是一行一行赋值给 {},可以用 {} 代替。
-n, --max-args=MAX-ARGS # 每个命令最多使用MAX-ARGS参数行
-P, --max-procs=MAX-PROCS # 一次运行最多的max-procs进程
-p, --interactive # 批量运行命令前交互式提示
-s, --max-chars=MAX-CHARS # 最多将命令限制为MAX-CHARS
-o, --open-tty # 在执行命令之前,在子进程中将stdin重新打开为/dev/tty;有助于运行
使用示例:
首先,定义一个测试用例文件,内有多行文本数据:
$ cat test.txt
a b c d e f
g h i j k l
m n o p q r
s t u v w x y z
-
1.多行输入单行输出和指定行输出
# 示例1.默认情况下的多行变单行处理
cat test.txt | xargs
# a b c d e f g h i j k l m n o p q r s t u v w x y z
# 示例2.指定每行显示3个参数
cat test.txt | xargs -n3
# a b c
# d e f
# g h i
# 示例3.指定每行显示4、6个参数
cat test.txt | xargs -n4
cat test.txt | xargs -n6
# 示例4.每次处理 5 个文件,到/backup 目录下
find . -name "*.jpg" | xargs -n 5 cp -t /backup/
ls /backup/
# 10.jpg 1.jpg 2.jpg 3.jpg 4.jpg 5.jpg 6.jpg 7.jpg 8.jpg 9.jpg
# 示例5.每次处理 10 个文件,移动到/destination 目录下
find /path/to/dir -name "*.jpg" | xargs -n 10 mv -t /destination/示例6.批量添加多个用户到linux中
echo user{1..10} | xargs -n1 useradd
-
2.指定一个定界符进行分割传递过来的参数字符串
# 默认情况下,xargs 是以换行符,或空格作为分隔符
echo -e "dir1\ndir2\ndir3" | xargs
# dir1 dir2 dir3
echo "nameXWeiyiGeekXnameX全栈工程师修炼指南" | xargs -dX
# name WeiyiGeek name 全栈工程师修炼指南
# 显示成为两列,这是我们需要的格式
echo "nameXWeiyiGeekXnameX全栈工程师修炼指南" | xargs -dX -n2
# name WeiyiGeek
# name 全栈工程师修炼指南
-
3.在执行命令之前进行确认,增加安全性:
echo "file1.txt file2.txt file3.txt" | xargs -p rm
# rm file1.txt file2.txt file3.txt ?...y
-
4.自定义定义一个占位符,以便在 xargs 中替换特定字符串。
echo "file1 file2 file3" | xargs -I {} mv {} {}.bak
# 示例1.复制所有图片文件到 /data/images/ 目录下,注意反斜杠
mkdir -vp /data/images/
ls *.png *.jpg *.gif | xargs -n1 -I {} cp {} /data/images/
# 示例2.查找当前目录下所有不可修改的文件 (对于入侵监测的时候可使用)
find . | xargs -I {} lsattr -a {} 2>/dev/null | grep '^----i'
-
5.并行执行命令,提高效率。
# 例1,同时压缩多个文件:
find . -name "*.log" | xargs -P 4 gzip
# 例2, 指定并行进程数为256,批量执行文件上传操作
thread_num=256
ls | xargs -n 1 -I {} -P ${thread_num} sh -c "/usr/binfs_upload_file /etcfs/client.conf {}"
ls -I '*.yml' | xargs -I {} rm -rf {}
# 例3.批量并行执行test.txt文件中,复制文件到到指定目录
cat test.txt <<'EOF'
cp ./0101/123456789.JPG ../2023/0101/123456789.jpg
cp ./0102/123456789.JPG ../2023/0102/123456789.jpg
cp ./0103/123456789.JPG ../2023/0103/123456789.jpg
EOF
cat test.txt | xargs -n 1 -I {} -P 256 sh -c "{}"
# 例4.并发执行多个进程进行文件下载
seq 100 | xargs -i -P10 wget -P /data http://share.weiyigeek.top/{}.zip
# 例5.并行下载B站视频
yum install python3-pip -y
pip3 install you-getseq 1 100 | xargs -i -P3 you-get https://www.bilibili.com/video/BV19D4y1D7UX?p={}
-
6.自定义处理空格和特殊字符
# 如果文件名中包含空格或特殊字符,可以使用 -print0 和 -0 选项,让参数以NULL分隔
find . -name "*.log" -print0 | xargs -0
# ./audit/audit.log ./sssd/sssd_implicit_files.log ./sssd/sssd_nss.log
# 或者使用 --null 选项,将换行符或空格作为文件名分隔符
find . -type f -name "*.log" -print0 | xargs -n1 --null
# ./audit/audit.log ./sssd/sssd_implicit_files.log ./sssd/sssd_nss.log
-
7.结合 find 命令使用的常规示例。
# 例1.删除某个目录下的所有 .tmp 文件
# 使用用 rm 删除太多的文件时候,可能得到一个错误信息:/bin/rm Argument list too long. 用xargs解决此问题。
find /dir -name "*.tmp" | xargs rm -f
# 例2.查找当前目录下所有 .txt 文件并统计它们的行数:
find . -name "*.txt" | xargs wc -l
# 例3.以 NULL 字符作为换行符,并以三列显示
find . -type f -name "*.log" -print0 | xargs -0 -n3
# ./tuned/tuned.log ./audit/audit.log ./anaconda/anaconda.log
# ./anaconda/X.log ./anaconda/program.log ./anaconda/packaging.log
# ./anaconda/storage.log ./anaconda/ifcfg.log ./anaconda/ks-script-ECgRju.log
# 例4.统计文件信息,统计一个源代码目录中所有php文件的行数
find . -type f -name "*.php" -print0 | xargs -0 wc -l
# 例5,查找当前目录下所有的jpg 文件,并且压缩它们
find . -type f -name "*.jpg" -print | xargs tar -czvf images.tar.gz
# 例6. 查询带有 SUID SHID SBIT 等权限的文件
find /bin -perm -7000 | xargs ls -Sl
-
8.读取stdin将格式化后的参数传递给命令
# 假设一个命令为 weiyigeek.sh 和一个保存参数的文件arg.txt:
# weiyigeek.sh 脚本命令内容,打印出所有参数
tee weiyigeek.sh <<'EOF'
#!/bin/bash
echo $*
EOF
# arg.txt 文件内容:
aaa
bbb
ccc
# 可以利用这个来更改ip文本以及脚本参数的传入
cat arg.txt | xargs -I {} ./weiyigeek.sh -p {} -l
cat arg.txt | xargs -I {} echo $* "-p123" {}"- l123"
-p aaa -l
-p bbb -l
-p ccc -l
-
9.在xargs中,可以使用 $* 获取所有参数, 以此来进行格式化拼接输出。
# 方式1.使用xargs格式化之后输出
cat url.txt | xargs -I {} echo $* "Url:"{}"/admin/web.jsp"
# 也可以使用awk一步搞定,后续我们也要介绍文件处理三剑客之一的命令
awk '{print "Url:"$1"/admin/web.jsp"}' url.txt
# Url:http://demo1.weiyigeek.top/admin/web.jsp
# Url:http://demo2.weiyigeek.top/admin/web.jsp
# Url:http://demo3.weiyigeek.top/admin/web.jsp
-
10.将 xargs 与其他命令结合使用,进行更复杂的操作:
# 例1.查找所有 .log 文件中包含 "Error" 的行,并对结果进行排序和去重,最后统计每个唯一行的出现次数
find /path/to/dir -name "*.log" | xargs grep "Error" | sort | uniq -c
# 假2,有一个文件包含了很多你希望下载的URL,你能够使用xargs下载所有链接
cat url-list.txt | xargs -P10 wget -c
原文地址:Linux 命令:每日一学,参数传递之xargs命令实践
若文章写得不错,不要吝惜手中转发,点赞、在看,若有疑问的小伙伴,可在评论区留言你想法哟💬!
温馨提示:作者最近10年的工作学习笔记(涉及网络、安全、运维、开发),需要学习实践笔记的看友,可添加作者账号[WeiyiGeeker],当前价格¥199,除了获得从业笔记的同时还可进行问题答疑以及每月远程技术支持,希望大家多多支持,收获定大于付出!
如果此篇文章对你有帮助,请你将它转发给更多的人!
学习推荐 往期文章