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 " | xargs #默认会使用echo命令输出,这里的换行符和空格以及制表符都被作为分隔符用来分割了
a b c dd y
[root@lgh test]# echo -e  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 " |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--  b
-rw-r--r--  c
-rw-r--r--  dd
-rw-r--r--  gg
-rw-r--r--  u t.txt #这是个特殊文件,有空格的文件名
-rw-r--r-- 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 
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:

51 10.log
-rw-r--r-- 123456789.log

现在需要把它们全部备份起来,编程*.log.bak文件

[root@lgh test]# ls | xargs  -i mv  {} {}.bak #这里使用-i接收,然后使用{}指定位置
[root@lgh test]# ll
total .log.bak
-rw-r--r-- 9.log.bak

-I则可以指定其他的符号、字母、数字作为替换符号,例如xargs -I

[root@lgh test]# ls | xargs  -I bb mv  bb bb.I #这里使用-I参数指定bb为接收替代符
[root@lgh test]# ll
total .log.bak.I
-rw-r--r-- 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 ?....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 t
/bin/echo .log.bak.I #打印执行的语句
.log.bak.I #打印执行语句的结果
/bin/echo .log.bak.I
.log.bak.I
/bin/echo 99.log.bak.I

2、-P:批量执行参数(并发,一起执行)哈哈,反正就是同时执行

在执行某一个命令的时候,后面很多参数的时候,例如:rm log/* 会对log下的每一个目录进行依次删除,就算使用xargs的分批执行,还是一个一个执行的,并不会提高效率,接下来该-P参数出场了

"-P N"选项可以指定并行处理的进程数量为N。不指定"-P"时,默认为1个处理进程,也就是串行执行。指定为0时,将尽可能多地开启进程数量

[root@lgh ~]# time echo {1..3} | xargs -n  sleep #不使用-P,并每个批次为1,总共的执行时间为6秒

real    0m6.005s
user    0m0.001s
sys     0m0.001s
[root@lgh ~]# time echo { sleep #不使用-P,每个批次为3,总共执行时间为6秒,分批不能提高速度

real    0m6.003s
user    0m0.000s
sys     0m0.002s
[root@lgh ~]# time echo {3 -P  sleep #使用-P,每个批次为3,说明只有一个批次,所以一个线程需要一次执行所有的命令,所以还是6秒,没有达到并发的效果

real    0m6.003s
user    0m0.001s
sys     0m0.000s
[root@lgh ~]# time echo { 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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


linux常用进程通信方式包括管道(pipe)、有名管道(FIFO)、信号(signal)、消息队列、共享内存、信号量、套接字(socket)。管道用于具有亲缘关系的进程间通信,有名管道的每个管道具有名字,使没有亲缘关系的进程间也可以通信。信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除
Linux性能观测工具按类别可分为系统级别和进程级别,系统级别对整个系统的性能做统计,而进程级别则具体到进程,为每个进程维护统计信息。

按实现原理分,可分为基于计数器和跟踪以及剖析。含义如下:

计数器:内核维护的统计数据,通常为无符号整型,用于对发生的事件计数,比如,网络包接收计数器,磁
本文详细介绍了curl命令基础和高级用法,包括跳过https的证书验证,详细追踪整个交互过程,可用于调用网络后端接口,诊断http和https网络服务故障。
本文包含作者工作中常用到的一些命令,用于诊断网络、磁盘占满、fd泄漏等问题。命令包括ping、fping、tcpdump、lsof、netstat、/proc/$pid/fd、du、grep、traceroute、dig。
linux的平均负载表示运行态和就绪态及不可中断状态(正在io)的进程数目,用uptime查看到负载很高,既有可能是CPU利用率高,也可能是大量在等待io的进程导致,用mpstat查看每个CPU的使用情况,查看CPU的使用率或者CPU花在等待io的时间,接着用pidstat定位具体的进程
CPU上下文频繁切换会导致系统性能下降,切换分为进程切换、线程切换及中断切换,进程切换的开销较大,除了需要保存寄存器和程序计数器中的值还需保存全局变量、栈等到内存中,以便下次运行恢复,而同一进程中的线程切换开销会小很多,只需更新寄存器和线程独有的栈,共享资源如打开的文件、全局变量等无需切换,当硬件中
1.top命令 作用:该命令可以按CPU使用.内存使用和执行时间对任务进行排序,常用来监控系统中占用CPU或内存较高的程序及CPU和内存的负载。 默认视图: 当想看系统负载时,可观察汇总的%CPU中的us用户进程和sy系统进程是否占用CPU很高,相加接近100%就说明占用很高了,有些程序可能得不到及
文章浏览阅读1.8k次,点赞63次,收藏54次。Linux下的目录权限!!!粘滞位!!!超详解!!!
文章浏览阅读1.6k次,点赞44次,收藏38次。关于Qt的安装、Windows、Linux、MacBook_mack book 安装qt
本文介绍了使用shell脚本编写一个 Hello
文章浏览阅读1.5k次,点赞37次,收藏43次。【Linux】初识Linux——了解操作系统的发展历史以及初次体验Linux编程环境
文章浏览阅读3k次,点赞34次,收藏156次。Linux超详细笔记,个人学习时很认真的记录的,觉得好的麻烦点个赞。
文章浏览阅读6.8k次,点赞109次,收藏114次。【Linux】 OpenSSH_9.3p1 升级到 OpenSSH_9.5p1(亲测无问题,建议收藏)_openssh_9.5p1
文章浏览阅读3.5k次,点赞93次,收藏78次。初识Linux中的线程,理解线程的各种概念,理解进程地址空间中的页表转换,介绍pthread线程库并理解线程库!
文章浏览阅读863次。出现此问题为Linux文件权限问题,解决方案为回到引擎目录执行命令。输入用户密码后运行./UnrealEditor。_increasing per-process limit of core file size to infinity.
文章浏览阅读2.9k次。使用文本编辑器:打开CSV文件,并使用文本编辑器(如Notepad++、Sublime Text、Visual Studio Code等)来查看文件的字符编码格式。通常在编辑器的底部状态栏或设置中可以找到当前编码的显示。请注意,上述方法并非绝对准确,特别是当文件没有明确的编码标识时。因此,如果你发现CSV文件在不同的工具或方法中显示不同的编码格式,可能需要进行进一步的分析和判断,或者尝试使用不同的编码转换方法。该命令将输出文件的MIME类型和编码信息。使用命令行工具:在命令行中,你可以使用。_shell读取csv文件逐行处理
本文介绍了如何在Linux系统中升级gcc版本,以便更好地支持C++11及以上版本的新特性。通过升级gcc,可以提升编译器的功能和性能,获得更好的开发体验。详细的步骤和方法请参考原文链接。
文章浏览阅读4.4k次,点赞6次,收藏19次。Mosquitto是一个开源的MQTT消息代理服务器。MQTT是一个轻量级的、基于发布/订阅模式的消息传输协议。 mosquitto的安装使用比较简单,可以方便的来进行一些测试。_linux mosquitto
文章浏览阅读7.2k次,点赞2次,收藏12次。Linux中,用于根目录下有一个.ssh目录,保存了ssh相关的key和一些记录文件。_~/.ssh/
文章浏览阅读4.5k次,点赞5次,收藏18次。首先需要安装 snmp ,使用下面的命令进行安装安装完毕之后,使用下面的命令查看是否安装成功当命令行显示如图即为安装成功。_snmp工具