xargs--冬天里的一丝暖意
本文为博客园作者所写: 一寸HUI,个人博客地址:https://www.cnblogs.com/zsql/
你有批量kill作业吗?有因为删除文件夹的内容太多而报错吗?-bash: /bin/rm: Argument list too long,查找出来的文件怎么直接删除呢?批量执行?并发执行?如果有这样的需求的话,就可以开始学习xargs命令了,本文主要的思路先提供一些简单的使用场景,然后再对xargs命令原理和使用进行阐述。
一、简单使用场景
1.1、使用场景
- 传递参数,从而组合多个命令
- 分隔数据,避免参数过长
- 不支持管道的命令
1.2、具体实例
1.1、批量删除hive用户的所有进程
ps aux | grep ^hive | grep -v grep | awk '{print $2}' | xargs kill -9
1.2、分批次删除logs目录下2020年的所有文件,每批为10个
cd /logs && ls | grep *2020* | xargs -n 10 rm -fr
ls /logs | sed "s:^:`pwd`/:" | grep *2020* | xargs -n 10 rm -fr
1.3、结合find命令进行处理文档,find命令可以查看:linux之find命令详解
find . -name *.log -print0 | xargs rm -f #查找当前目录下的所有log文件,并删除
find ./ -type f -name "*.txt" | xargs -i cp {} /tmp/ #查找txt文件,并复制到/tmp目录下
find ./ -type f -name "*.log" | xargs -i -t tar -zcvf {}.tar.gz {} #压缩日志文件
1.4、批量下载
cat urls.txt | xargs wget
1.5、如果打通了ssh免密,假如有ip:192.168.88.130,192.168.88.131
echo "192.168.88.130,192.168.88.131" | xargs -n 1 -P 2 -I __ip__ scp root@__ip__:/var/log/cron ./__ip__.cron #把这两个机器的cron日志复制到本地,取名为${ip}.cron
二、原理和使用
2.1、使用语法
[root@lgh~]# xargs --help
Usage: xargs [-0prtx] [--interactive] [--null] [-d|--delimiter=delim]
[-E eof-str] [-e[eof-str]] [--eof[=eof-str]]
[-L max-lines] [-l[max-lines]] [--max-lines[=max-lines]]
[-I replace-str] [-i[replace-str]] [--replace[=replace-str]]
[-n max-args] [--max-args=max-args]
[-s max-chars] [--max-chars=max-chars]
[-P max-procs] [--max-procs=max-procs] [--show-limits]
[--verbose] [--exit] [--no-run-if-empty] [--arg-file=file]
[--version] [--help] [command [initial-arguments]]
2.2、原理说明
在1.1中我们说了xargs使用的三个场景,一个是参数太长导致命令不能执行,就像rm一样,如果rm -rf /log/*,正如log目录下有很多很多个文件,这样就会出现/bin/rm: Argument list too long这样的错误,那为啥使用xargs就能删除了呢,因为xargs默认会把参数截取分批进行执行,这里使用了xargs的分割数据和传递参数原理,还有就是有些命令并不支持管道符,像ls命令,但是又想使用一行命令搞定,这样就可以使用xargs配合使用了。比如使用命令:echo text.txt | xargs cat,这样可以把text.txt传递给cat命令作为参数,这样就可以查看该文件了,也就是说xargs完成了两个行为:处理管道传输过来的stdin;将处理后的传递到正确的位置上,还可以将stdin或者文件stdin分割成批,每个批中有很多分割片段,然后将这些片段按批交给xargs后面的命令进行处理,可能看到这里会有点懵逼,那简单点就是:xargs处理的优先级或顺序了:先分割,再分批,然后传递到参数位。
举个例子:假如你有一个蛋糕,你要分给10个孩子去吃,首先第一步要进行切蛋糕(分割)那怎么切呢,切10块还是20块或者其他呢?所以这里就会存在切蛋糕方式的选择(分割方式),切好蛋糕后,小孩子都在不同的地方,你是选择每次送一块蛋糕呢,还是一次送两块呢(这就是分批,每批次传送多少个),送也要找到小孩的位置才能送到他手上吧,(这就是把分好批的文件或数据传递到命令指定的参数的位置),我想大家应该比较容易理解这个了,如果你还是没能理解,多看几遍:xargs处理的优先级或顺序了:先分割,再分批,然后传递到参数位,然后继续看下面的参数例子就懂了
2.3、参数详解
2.3.1、分割参数
分割有三种方法:独立的xargs、xargs -d和xargs -0,后两者可以配合起来使用,既然都可以用来分割,那我们看看分割的方式:
1、xargs分割:将接收到的stdout处理后传递到xargs后面的命令参数位,不写命令时默认的命令是echo,会对空格、tab、换行符,反斜线等进行分割
[root@lgh test]# echo -e "a b c \n dd \t y"
a b c
dd y
[root@lgh test]# echo -e "a b c \n dd \t y" | xargs #默认会使用echo命令输出,这里的换行符和空格以及制表符都被作为分隔符用来分割了
a b c dd y
[root@lgh test]# echo -e "a b c \n dd \t y" | xargs echo
a b c dd y
将所有空格、制表符和分行符都替换为空格并压缩到一行上显示,这一整行将作为一个整体,这个整体的所有空格属性继承xargs处理前的符号属性(大概理解为,把这些分割好后用自己的所要的“段”替代,干掉别人的心腹(分隔符),换成自己的心腹)
2、xargs -d分割:可以指定分段符,可以是单个符号、字母或数字。如指定字母o为分隔符:xargs -d"o"
[root@lgh test]# echo -e "a bd\n cod \n dod \t y"
a bd
cod
dod y
[root@lgh test]# echo -e "a bd\n cod \n dod \t y" |xargs -d 'o' #使用o进行分割,但是这样可能看的不是很清楚
a bd
c d
d d y
这样看可能就清楚了:
[root@lgh test]# echo -e "a bd\n cod \n dod \t y" |xargs -p -n 1 -d "o" #-p参数交互参数,-n 1执行每批的个数,这些后面会说到
/bin/echo a bd
c ?... #打印第一批
/bin/echo d
d ?... #打印第二批
/bin/echo d y
?... #打印第三批
/bin/echo ?...
从上就可以看出来是指定的字符"o"进行分割了,使用xargs -d分割,会忽略空格、制表符、分行符等这些符号,会把这些当做内容保留下来,如上面的换行符都有保留下来,只有指定的"o"才是分割符
3、xargs -0分割:可以处理接收的stdin中的null字符(\0),其实可以理解是xargs -d的一种特列,等价于xargs -d "\0"
[root@mvxl2685 test]# echo -e "1\tbbb \n uu\0dddd"
1 bbb
uudddd
[root@mvxl2685 test]# echo -e "1\tbbb \n uu\0dddd" | xargs -0
1 bbb
uu dddd
[root@mvxl2685 test]# echo -e "1\tbbb \n uu\0dddd" | xargs -0 -p -n 1
/bin/echo 1 bbb
uu ?... #第一批
/bin/echo dddd
?... #第二批
/bin/echo ?...
上面三种分割方式,使用最多的也就是默认的xargs了
分割行为 |
特殊符号处理方式 |
分段方法 |
配合分批选项 |
分批方法 |
xargs |
空格、制表符、分行符替换为空格,引号和反斜线删除。处理完后只有空格。如果空格、制表符和分行符使用引号包围则可以保留 |
结果继承处理前的符号性质(文本符号还是标记意义符号)。 |
-n |
以分段结果中的每个空格分段,进而分批。不管是文本还是标记意义的空格,只要是空格 |
-L、-i |
以标记意义上的空格分段,进而分批 |
|||
不指定 |
结果作为整体输出 |
|||
xargs -d |
xargs -d 不处理文本意义上的符号,所有标记意义上的符号替换为换行符\n,将-d指定的分割符替换为标记意义上的空格。 结果中除了最后的空行和-d指定的分割符位的分段空格,其余全是文本意义上的符号 |
按照-d指定的符号进行分段,每个段中可能包含文本意义上的空格、制表符、甚至是分行符。 |
-n、-L、-i |
以标记意义上的符号(即最后的空行和-d指定分隔符位的空格)分段,进而分批。分段结果中保留所有段中的符号,包括制表符和分行符。 |
不指定 |
结果作为整体输出 |
|||
xargs -0 |
不处理文本意义上的符号,将非\0的标记意义上的符号替换为\n,将\0替换为空格。 结果中除了最后空行和\0位的空格,其余都是文本意义上的符号 |
以替换\0位的空格分段,每个段中可能包含文本意义上的空格、制表符、甚至是分行符。 如果没检测到\0,则只有一个不可分割的段。 |
-n、-L、-i |
检测到\0时,以标记意义上的符号(即最后的空行和\0位的空格)分段,进而分批。分段结果中保留所有段中的符号,包括制表符和分行符。 |
未检测到\0时,整个结果作为不可分割整体,使用分批选项是无意义的 |
||||
不指定 |
结果作为整体输出 |
2.3.2、分批参数
上面一节中我们知道怎么切蛋糕了(分割),接下来我们就怎么把这些分割好的内容组装成批次。可以使用-n和-L两个参数,那具体他们有什么区别呢?请继续往下看:
1、使用-n分批
假如有文件夹test:
[root@lgh test]# ll
total 0
-rw-r--r-- 1 root root 0 Dec 4 14:33 a
-rw-r--r-- 1 root root 0 Dec 4 14:33 b
-rw-r--r-- 1 root root 0 Dec 4 14:33 c
-rw-r--r-- 1 root root 0 Dec 4 14:33 dd
-rw-r--r-- 1 root root 0 Dec 4 14:33 gg
-rw-r--r-- 1 root root 0 Dec 4 14:33 u t.txt #这是个特殊文件,有空格的文件名
-rw-r--r-- 1 root root 0 Dec 4 14:33 uu
接下我们使用-n分批会有怎样的效果呢?
[root@lgh test]# ls | xargs -n 2 #每两个作为一个批次
a b
c dd
gg u #这里把u t.txt文件拆到两个批次中了,这并不是我们想要的
t.txt uu
xargs -n分两种情况:和独立的xargs一起使用,这时按照每个空格分段划批;和xargs -d或xargs -0一起使用,这时按段分批,即不以空格、制表符和分行符分段划批
2、使用-L分批
[root@lgh test]# ls | xargs -L 2 #每两个作为一个批次
a b
c dd
gg u t.txt #这里就没有拆分u t.txt文件
uu
-n选项类似,唯一的区别是-L永远是按段划批,而-n在和独立的xargs一起使用时是按空格分段划批的
2.3.3、位置传递参数
xargs -i和xargs -I选项在逻辑上用于接收传递的分批结果,如果不使用这两个选项,则默认是将分割后处理后的结果整体传递到命令的最尾部,有时候可能需要到多个位置,或者不是最后一个位置,例如cp命令一样,所以这两个参数很重要。
使用xargs -i时以大括号{}作为替换符号,传递的时候看到{}就将被结果替换。可以将{}放在任意需要传递的参数位上,如果多个地方使用{}就实现了多个传递
假如有目录test:
[root@lgh test]# ll
total 0
-rw-r--r-- 1 root root 0 Dec 4 14:51 10.log
-rw-r--r-- 1 root root 0 Dec 4 14:51 1.log
-rw-r--r-- 1 root root 0 Dec 4 14:51 2.log
-rw-r--r-- 1 root root 0 Dec 4 14:51 3.log
-rw-r--r-- 1 root root 0 Dec 4 14:51 4.log
-rw-r--r-- 1 root root 0 Dec 4 14:51 5.log
-rw-r--r-- 1 root root 0 Dec 4 14:51 6.log
-rw-r--r-- 1 root root 0 Dec 4 14:51 7.log
-rw-r--r-- 1 root root 0 Dec 4 14:51 8.log
-rw-r--r-- 1 root root 0 Dec 4 14:51 9.log
现在需要把它们全部备份起来,编程*.log.bak文件
[root@lgh test]# ls | xargs -i mv {} {}.bak #这里使用-i接收,然后使用{}指定位置
[root@lgh test]# ll
total 0
-rw-r--r-- 1 root root 0 Dec 4 14:51 10.log.bak
-rw-r--r-- 1 root root 0 Dec 4 14:51 1.log.bak
-rw-r--r-- 1 root root 0 Dec 4 14:51 2.log.bak
-rw-r--r-- 1 root root 0 Dec 4 14:51 3.log.bak
-rw-r--r-- 1 root root 0 Dec 4 14:51 4.log.bak
-rw-r--r-- 1 root root 0 Dec 4 14:51 5.log.bak
-rw-r--r-- 1 root root 0 Dec 4 14:51 6.log.bak
-rw-r--r-- 1 root root 0 Dec 4 14:51 7.log.bak
-rw-r--r-- 1 root root 0 Dec 4 14:51 8.log.bak
-rw-r--r-- 1 root root 0 Dec 4 14:51 9.log.bak
-I则可以指定其他的符号、字母、数字作为替换符号,例如xargs -I
[root@lgh test]# ls | xargs -I bb mv bb bb.I #这里使用-I参数指定bb为接收替代符
[root@lgh test]# ll
total 0
-rw-r--r-- 1 root root 0 Dec 4 14:51 10.log.bak.I
-rw-r--r-- 1 root root 0 Dec 4 14:51 1.log.bak.I
-rw-r--r-- 1 root root 0 Dec 4 14:51 2.log.bak.I
-rw-r--r-- 1 root root 0 Dec 4 14:51 3.log.bak.I
-rw-r--r-- 1 root root 0 Dec 4 14:51 4.log.bak.I
-rw-r--r-- 1 root root 0 Dec 4 14:51 5.log.bak.I
-rw-r--r-- 1 root root 0 Dec 4 14:51 6.log.bak.I
-rw-r--r-- 1 root root 0 Dec 4 14:51 7.log.bak.I
-rw-r--r-- 1 root root 0 Dec 4 14:51 8.log.bak.I
-rw-r--r-- 1 root root 0 Dec 4 14:51 9.log.bak.I
注意:-i、-L、-n这三个参数在一起,都会被最后一个覆盖,也就是一起使用的时候,只有最后一个生效
2.3.4、其他参数
上面已经把最重要的一些参数介绍完了,我们看看其他参数
1、-p和-t:交互参数,可以用于前期不确定执行过程,用来测试自己写的代码是否符合最终的执行命令
-p是询问是否打印,y键表示打印,回车表示不打印
[root@lgh test]# ls | xargs -n 3 -p
/bin/echo 10.log.bak.I 1.log.bak.I 2.log.bak.I ?...y #询问打印,按下y
/bin/echo 3.log.bak.I 4.log.bak.I 5.log.bak.I ?...10.log.bak.I 1.log.bak.I 2.log.bak.I #打印出上一次询问的值,然后继续询问下一个批次是否打印,按下回车,不打印输出 /bin/echo 6.log.bak.I 7.log.bak.I 8.log.bak.I ?...
/bin/echo 9.log.bak.I ?...
-t是先把执行的语句打印出来,然后把要输出的内容打印出来
[root@lgh test]# ls | xargs -n 3 -t
/bin/echo 10.log.bak.I 1.log.bak.I 2.log.bak.I #打印执行的语句
10.log.bak.I 1.log.bak.I 2.log.bak.I #打印执行语句的结果
/bin/echo 3.log.bak.I 4.log.bak.I 5.log.bak.I
3.log.bak.I 4.log.bak.I 5.log.bak.I
/bin/echo 6.log.bak.I 7.log.bak.I 8.log.bak.I
6.log.bak.I 7.log.bak.I 8.log.bak.I
/bin/echo 9.log.bak.I
9.log.bak.I
2、-P:批量执行参数(并发,一起执行)哈哈,反正就是同时执行
在执行某一个命令的时候,后面很多参数的时候,例如:rm log/* 会对log下的每一个目录进行依次删除,就算使用xargs的分批执行,还是一个一个执行的,并不会提高效率,接下来该-P参数出场了
"-P N"选项可以指定并行处理的进程数量为N。不指定"-P"时,默认为1个处理进程,也就是串行执行。指定为0时,将尽可能多地开启进程数量
[root@lgh ~]# time echo {1..3} | xargs -n 1 sleep #不使用-P,并每个批次为1,总共的执行时间为6秒 real 0m6.005s
user 0m0.001s
sys 0m0.001s
[root@lgh ~]# time echo {1..3} | xargs -n 3 sleep #不使用-P,每个批次为3,总共执行时间为6秒,分批不能提高速度 real 0m6.003s
user 0m0.000s
sys 0m0.002s
[root@lgh ~]# time echo {1..3} | xargs -n 3 -P 3 sleep #使用-P,每个批次为3,说明只有一个批次,所以一个线程需要一次执行所有的命令,所以还是6秒,没有达到并发的效果 real 0m6.003s
user 0m0.001s
sys 0m0.000s
[root@lgh ~]# time echo {1..3} | xargs -n 1 -P 3 sleep #使用-P,每个批次为1,所以可以同时执行命令,执行时间为3秒 real 0m3.003s
user 0m0.001s
sys 0m0.001s
很多时候,执行大量命令的时候可以使用-P提高效率
2.4、总结
xargs命令很强大,你值得拥有!!!如果使用的得当不仅可以提高逼格,还可以提高效率,能够做一些原本命令不能做到的事情,好好学号xargs何乐而不为呢?
xargs的总结:分割(xargs,xargs -d,xargs -0)、分批(-n,-L)、传递到指定位置(-i,-I)
参考:
https://www.cnblogs.com/f-ck-need-u/p/5925923.html#auto_id_9
https://blog.chenyuanwai.com/xargs/
https://blog.csdn.net/lilongsy/article/details/77535687
xargs--冬天里的一丝暖意的更多相关文章
- SXOI2018 游记
noilinux@Capella:~$ cd /Memories/ noilinux@Capella:/Memories$ rm *SXOI* rm:是否删除有写保护的普通文件 "SXOI2 ...
- 毕业三年从月薪6K到20K
首先,声明这不是标题党,是一个真实的北漂故事! 为什么写这篇文章呢?第一,有感而发,感恩遇到的人和事,其次,希望对读这篇文章的你有所帮助 毕业那年 时间追溯到17年6月30号,那天毕业典礼,之 ...
- 设计模式(九): 从醋溜土豆丝和清炒苦瓜中来学习"模板方法模式"(Template Method Pattern)
今天是五.四青年节,祝大家节日快乐.看着今天这标题就有食欲,夏天到了,醋溜土豆丝和清炒苦瓜适合夏天吃,好吃不上火.这两道菜大部分人都应该吃过,特别是醋溜土豆丝,作为“鲁菜”的代表作之一更是为大众所熟知 ...
- 每天一个 Linux 命令(21):find命令之xargs
在使用 find命令的-exec选项处理匹配到的文件时, find命令将所有匹配到的文件一起传递给exec执行.但有些系统对能够传递给exec的命令长度有限制,这样在find命令运行几分钟之后,就会出 ...
- [Linux] xargs 和 管道符的区别
今天刚好遇到需要使用xargs的情况,就来研究一下xargs 和 管道符的区别 举几个例子,下面两个语句执行后的结果是什么呢? 1. zhang$ find . -name "*.prope ...
- 设计窘境:来自 Repository 的一丝线索,Domain Model 再重新设计
写在前面 阅读目录: 疑惑解读 设计窘境 一幅图的灵感 为嘛还是你-Repository 后记 上一篇<No zuo no die:DDD 应对具体业务场景,Domain Model 重新设计& ...
- 如丝般顺滑地从Windows迁移SQLServer数据库到Linux
老鸟看过菜鸟的上一篇<MSSQL On Linux备份与还原>文章后,很满意,但是还是忍不住发问:"这篇文章讲的是MSSQL在Linux系统上的备份与还原,如果我之前是Windo ...
- xargs -I
xargs -i 参数或者-I参数配合{}即可进行文件的操作. -I replace-str Replace occurrences of replace-str ...
- find / -type f -name "*fetion*" |xargs rm -rf {}\
find / -type f -name "*fetion*" |xargs rm -rf {}\
随机推荐
- IOC容器小结
IOC容器: Ioc-Inversion of Control,即"控制反转",就是具有依赖注入功能的容器,是可以创建对象的容器,IOC容器负责实例化.定位.配置应用程序中的对象及 ...
- sdsdsd
create PROCEDURE b2(in c_year int,in co int)begin declare num int; if exists(select * from class whe ...
- 聚类之k-means附代码
import osimport sys as sys#reload(sys)#sys.setdefaultencoding('utf-8')from sklearn.cluster import KM ...
- Azure Data Factory(四)集成 Logic App 的邮件通知提醒
一,引言 上一篇有介绍到使用Azure Data Factory 复制数据,然后有集成 Azure DevOps 实现CI/CD,但是对于真正的项目来说,这些肯定是不够的,比如说在执行 Azure P ...
- Pandas_工资集处理
import numpy as np import pandas as pd from pandas import Series,DataFrame # 1--读取数据文件 file_obj=open ...
- Java7 新特性 —— java.nio.file 文件操作
本文部分摘自 On Java 8 自 Java7 开始,Java 终于简化了文件读写的基本操作,新增了 java.nio.file 库,通过与 Java8 新增的 stream 结合可以使得文件操作变 ...
- 一文解析TCP/UDP
声明:本文部分内容来自互联网.书籍等渠道,表示感谢: 转载请注明出处:@热风.https://www.cnblogs.com/refeng/p/13996657.html 目录 TCP/UDP详解 1 ...
- 定位一个网络问题引起的ceph异常
前言 有一个ceph环境出现了异常,状态就是恢复异常的慢,但是所有数据又都在走,只是非常的慢,本篇将记录探测出问题的过程,以便以后处理类似的问题有个思路 处理过程 问题的现象是恢复的很慢,但是除此以外 ...
- IDA-hook so层方法与java之间的映射关键
第一步 1.首先用ida打开so文件 第二步 第三步
- a标签禁用
a标签禁用可以使用CSS3的特性来控制 <a class="disabled">我是a标签</a> a.disabled { pointer-events: ...