xargs的使用

author author     2022-10-09     763

关键词:

Xargs的使用

 

发现xargs是个很好用的命令,于是搜索了网上好多关于xargs的文章并做了相关的实验,现自己总结一下,好转化为自己的东西:

Xargs经常会与管道搞混淆,所以

 

首先我们先了解下管道的作用:

? 管道实现的是:将前面的stdout作为后面的stdin进行传递。但有些命令是不接受管道的传递方式,比如:ls (#echo /root| ls 

? 管道传递过来的stdin只能作为内容而不是参数。或者说是管道无法正确传递到后面命令的参数位:(#echo --help| cat ,区别于#echo --help| xargs cat 

 

鉴于管道功能上的局限,所以xargs的作用就显现出来了:

 

? Xargs实现的是将管道传输过来的stdin进行处理后,传递到命令的参数上。xargs完成了两个动作:A.处理管道传输过来的stdin B.将处理后的stdin传递到正确的位置上

 

 Xargs的作用不仅仅限于简单的stdin传递到命令的参数位。它还可以将stdin或者文件stdin分割成批,每个批中有很多分割片段,然后将这些片段按批交给xargs后面的命令进行处理。

 

 Xargs默认其后面的命令是echoecho a.txt| xargs = echo a.txt| xargs echo“)而空格是其默认的定界符。

 

 Xargs会把管道传递过来的stdin里的换行符,空白换成空格取代,形成一行作为整体输出:

[[email protected] tmp]# cat c.txt

a.txt

b.txt

[[email protected] tmp]# cat c.txt | xargs

a.txt b.txt

即:如果不指定分批选项(-i,-L,-n),Xargs的一整行结果将作为一个整体输出,而不是分隔开的!

 

 Xargs一些比较常用的选项:

分割选项:-d ,-0 | 分批选项: -n,-L,-i/-I | 使用-p或-t来观察命令的执行过程

分割选项 -d, -0:分割前会对stdin分批做一个分行动作,然后才进行分割

-d 指定分隔符

[[email protected] testfile]# cat list.txt

a1.bak,a2.bak,a3.bak,a4.bak

[[email protected] testfile]# cat list.txt | xargs -d','

a1.bak a2.bak a3.bak a4.bak

                        <——分割后输出会多出分行符,会对后续的命令有影响

[[email protected] testfile]# cat list.txt | xargs -d',' cat

this is a1

this is a2

this is a2.

this is a3

this is a3.

this is a3..

cat: a4.bak

: 没有那个文件或目录<——这里就因为分割输出多出的那一空行导致a4.bak文件无法读出

[[email protected] testfile]#

正确的命令应该为:cat list.txt | xargs -d',' |xargs cat

 

-0 指定固定的作为分隔符。

其实xargs -0就是特殊的xargs -d的一种,它等价于xargs -d""。

表示字符串结束,即字符串都是以结束的)

 

如果使用xargs -0时不指定分批选项(-n、-L、-i),则处理后的结果将作为一个整体输出。

[[email protected] testfile]# ls | xargs

a1.bak a2.bak a3.bak a4.bak a5.bak a8.bak a9.bak list1.txt list.txt

[[email protected] testfile]# ls | xargs -0

a1.bak

a2.bak

a3.bak

a4.bak

a5.bak

a8.bak

a9.bak

list1.txt

list.txt

 

[[email protected] testfile]#

如果指定了分批选项,但没有检测到null字符,则整个结果将称为一个不可分割整体,这时使用分批选项是完全无意义的

[[email protected] testfile]# ls | xargs -0 -n 3

a1.bak

a2.bak

a3.bak

a4.bak

a5.bak

a8.bak

a9.bak

list1.txt

list.txt

 

[[email protected] testfile]#

如果指定了分批选项,并且检测到了null字符,则以位的空格分段划批,这时使用-n、-L或-i的结果是一样的

[[email protected] testfile]# ls |tr " " ""| xargs -0 -n 3

a1.bak a2.bak a3.bak

a4.bak a5.bak a8.bak

a9.bak list1.txt list.txt

[[email protected] testfile]# ls |tr " " ""| xargs -0 -L 3

a1.bak a2.bak a3.bak

a4.bak a5.bak a8.bak

a9.bak list1.txt list.txt

[[email protected] testfile]#

 

find -print0可以输出字符 ,所以会和xargs -0 结合一起来用 

 

分批选项:-n,-L,-i/-I: 分批用于指定每次传递多少个分段(参数)。

 

-i选项优先级最高,-L选项次之,-n选项优先级最低。

多个分批选项同时指定时,高优先级的选项会覆盖低优先级的选项。也就是说这时候指定低优先级的选项是无意义的。

 

    -n 该选项表示将xargs生成的命令行参数,每次传递几个参数给其后面的命令执行

-L -n选项类似,唯一的区别是-L永远是按段分段划批,而-n在和独立的xargs一起使用是按空格分段划批的。

-i 选项在逻辑上用于接收传递的分批结果。

-I -i是一样的,只是-i默认使用大括号作为替换符号,-I则可以指定其他的符号、字母、数字作为替换符号,但是必须用引号包起来。

 

实例:

[[email protected] testfile]# ls

a1.bak  a2.bak  a3.bak  a4.bak  a5.bak  a8.bak  a9.bak  list1.txt  list.txt  my note.log

[[email protected] testfile]# ls |xargs -n3 <-- 这里-n空格分段划批

a1.bak a2.bak a3.bak

a4.bak a5.bak a8.bak

a9.bak list1.txt list.txt

my note.log

[[email protected] testfile]# 

[[email protected] testfile]# ls |xargs -d'k' -n3 <-- -n-d配合使用,按有‘k’段分批

a1.ba

a2.ba

a3.ba

 

a4.ba

a5.ba

a8.ba

 

a9.ba

list1.txt

list.txt

my note.log

 

[[email protected] testfile]#

----------------------- ------------------- -------------- -----------------------

[[email protected] testfile]# ls | xargs  -n1

a1.bak

a2.bak

a3.bak

a4.bak

a5.bak

a8.bak

a9.bak

list1.txt

list.txt

my          <-- -n这里是以空格为段划批,这里的my不是存在的文件名

note.log      <-- “my  note.log才是正确的文件名

[[email protected] testfile]# ls | xargs  -L1

a1.bak

a2.bak

a3.bak

a4.bak

a5.bak

a8.bak

a9.bak

list1.txt

list.txt

my note.log   <-- -L这里是一直以段为段划批

[[email protected] testfile]#

------ -----------  ----------------  ------------

-i 选项在逻辑上用于接收传递的分批结果。

如果不使用-i,则默认是将分割后处理后的结果整体传递到命令的最尾部。而用了-i可以传递多个参数位,而不是仅仅最尾端的参数位。例如重命名备份的时候在每个传递过来的文件名加上后缀.bak,这需要两个参数位。

使用xargs -i时以大括号{}作为替换符号,传递的时候看到{}就将被结果替换。可以将{}放在任意需要传递的参数位上,如果多个地方使用{}就实现了多个传递。

[[email protected] one]# touch day{1..7}

[[email protected] one]# ls

day1  day2  day3  day4  day5  day6  day7

[[email protected] one]# ls | xargs -i mv {}  {}.bak <-- 完成了两个参数位的传递

[[email protected] one]# ls

day1.bak  day2.bak  day3.bak  day4.bak  day5.bak  day6.bak  day7.bak

[[email protected] one]# 

-I只是可以自定义其替换符号:

[[email protected] one]# ls | xargs -Ix mv x x.bak <-- 跟上面的命令效果一样

[[email protected] testfile]# ls | xargs  -L3

a1.bak a2.bak a3.bak

a4.bak a5.bak a8.bak

a9.bak list1.txt list.txt

my note.log

------ ------------- -------------

体会一下有-i和没有-i的区别:

[[email protected] testfile]# ls | xargs  -L3  -i  cat {}

this is a1

this is a2

this is a2.

this is a3

this is a3.

this is a3..

this is a4

this is a4.

this is a4..

this is a4...

a1.bak,a2.bak

a3.bak,a4.bak

a5.bak,a8.bak

a9.bak

a1.bak,a2.bak,a3.bak,a4.bak

i am log of my note

[[email protected] testfile]# ls | xargs -L3 cat

this is a1

this is a2

this is a2.

this is a3

this is a3.

this is a3..

this is a4

this is a4.

this is a4..

this is a4...

a1.bak,a2.bak

a3.bak,a4.bak

a5.bak,a8.bak

a9.bak

a1.bak,a2.bak,a3.bak,a4.bak

cat: my: 没有那个文件或目录

cat: note.log: 没有那个文件或目录  <-- 可见没有-i传递的参数会被误解分割了

[[email protected] testfile]#

 

 

使用-p或-t来观察命令的执行过程  

[[email protected] testfile]# ls | xargs -L3 -p cat

cat a1.bak a2.bak a3.bak ?...yes  <-- 询问是否这样执行命令,输入y或yes将执行

cat a4.bak a5.bak a8.bak ?...this is a1

this is a2

this is a2.

this is a3

this is a3.

this is a3..

yes  <--- 同上

cat a9.bak list1.txt list.txt ?...this is a4

this is a4.

this is a4..

this is a4...

yes  <-- 同上

cat my note.log ?...a1.bak,a2.bak

a3.bak,a4.bak

a5.bak,a8.bak

a9.bak

a1.bak,a2.bak,a3.bak,a4.bak

yes  <--  同上

cat: my: 没有那个文件或目录  <-- 这里就看出来分批传递到这里后出问题了因为cat没法对“my  note.log”文件处理,它分解成了my和note.log两个不存在的文件,所以提示没有那个文件或者目录

cat: note.log: 没有那个文件或目录

[[email protected] testfile]#

[[email protected] testfile]# ls | xargs -L3 -i -p cat {}

cat a1.bak ?...y

cat a2.bak ?...this is a1

y

cat a3.bak ?...this is a2

this is a2.

y

cat a4.bak ?...this is a3

this is a3.

this is a3..

y

cat a5.bak ?...this is a4

this is a4.

this is a4..

this is a4...

y

cat a8.bak ?...y

cat a9.bak ?...y

cat list1.txt ?...y

cat list.txt ?...a1.bak,a2.bak

a3.bak,a4.bak

a5.bak,a8.bak

a9.bak

y

cat my note.log ?...a1.bak,a2.bak,a3.bak,a4.bak

y

i am log of my note

[[email protected] testfile]#

这里# ls | xargs -L3 -i -p cat {}就可以看出来-i是按逻辑上一个一个传递参数(-i按分段来传递,无法按批来传递),这里-i的优先权大于-L,所以这里的-L是无意义的。

 

 xargs主要是为find服务的

 

我们要删除一个带空格的文件:

[[email protected] one]# touch a b c "my  note.log"

[[email protected] one]# ls

a  b  c  my  note.log

[[email protected] one]#

[[email protected] one]# find . -name *.log

./my  note.log

[[email protected] one]# find . -name *.log | xargs rm -fr <- 这样是没法删除的,rm只是解读为删除./my 的文件,并不是./my note.log这个文件

[[email protected] one]# ls

a  b  c  my  note.log

[[email protected] one]# find . -name *.log -print0| xargs -0 rm -fr <-- 通常用find -print0来结合xargs -0 来处理,但没有通用性,别的命令无法用这个方法

[[email protected] one]# ls

a  b  c

[[email protected] one]# touch "my note.log"

[[email protected] one]# find . -name *.log | xargs -i rm -fr "{}" <-- 这种方法相对会有通用性,别的命令也能使用

[[email protected] one]# ls

a  b  c

[[email protected] one]#

Ps:

Linux命令一般可以从两个地方读取要处理的内容,一个是通过命令行参数,二是通过标准输入。但是很多命令的设计是先从命令行参数中获取参数,然后才是从标准输入stdin中读取。(大多数命令有一个参数 “-”,来表示从标准输入中读取)

 

[[email protected] tmp]# cat a.txt

this is a.txt

i love u !

u love me ?

[[email protected] tmp]# echo "my love" | cat a.txt <- 只会先读取命令行参数所以只读了a.txt

this is a.txt

i love u !

u love me ?

[[email protected] tmp]# echo "my love" | cat a.txt -  <- 这里多加了一个横杠,表stdin,所以读了a.txt再读了echo的内容(注意先后顺序)

this is a.txt

i love u !

u love me ?

my love

[[email protected] tmp]# echo "my love" | grep 'love'  a.txt

i love u !

u love me ?

[[email protected] tmp]# echo "my love" | grep 'love'  a.txt -

a.txt:i love u !

a.txt:u love me ?

(标准输入):my love

[[email protected] tmp]#

 

find与xargs配合使用(代码片段)

在使用find命令的-exec选项处理匹配到的文件时,find命令将所有匹配到的文件一起传递给exec执行。但有些系统对能够传递给exec的命令长度有限制,这样在find命令运行几分钟之后,就会出现溢出错误。错误信息通常是“参数列太... 查看详情

使用 xargs 调用 shell 函数

】使用xargs调用shell函数【英文标题】:Callingshellfunctionswithxargs【发布时间】:2012-06-1517:37:20【问题描述】:我正在尝试使用xargs来并行调用更复杂的函数。#!/bin/bashecho_var()echo$1return0seq-f"n%04g"1100|xargs-n1-P10-iecho_varexit0这会返回错误... 查看详情

如何使用 xargs 复制名称中包含空格和引号的文件?

】如何使用xargs复制名称中包含空格和引号的文件?【英文标题】:HowcanIusexargstocopyfilesthathavespacesandquotesintheirnames?【发布时间】:2010-09-1316:16:20【问题描述】:我正在尝试复制目录下的一堆文件,并且其中一些文件的名称中有... 查看详情

老男孩教育每日一题-2017年5月19日-使用find命令的时候|xargs(管道xargs)与-exe有什么区别?

1.题目老男孩教育每日一题-2017年5月19日-使用find命令的时候|xargs(管道xargs)与-exe有什么区别?2.参考答案一般来说这两个参数或命令是一样的。可是在一些情况下尤其是打包压缩的时候差别就很大了。find/oldboy-typef|xargs find命... 查看详情

xargs 字符串用作 agrep 的输入

...布时间】:2012-06-2101:21:22【问题描述】:伙计们,我正在使用xargs将输入传递给agrep。我正在使用如下所示的xargsScript:xargs-L1-Istringecho"RequestId="string|xargs-L1-IstringzcatFILEB|agrep-dEOEstringO 查看详情

xargs原理&使用

1.简介  之所以能用到这个命令,是由于很多linux命令不支持用管道传递参数,例如  find /sbin -perm +700 |ls -l  这个命令是错误的  find /sbin -perm +700 |xargs ls -l   这样才... 查看详情

xargs

xargs紧跟在管道操作符之后,它使用标准输入作为主要的数据源例如:ls*.c|xargsgrepmainxargs默认会执行echo命令1.将多行输入转换成单行输出catexample.txt|xargs2.将单行输入转换成多行输出catexample.txt|xargs-n3xargs工作原理:xargs命令接受来... 查看详情

xargs原理&使用(代码片段)

...xargs后面的命令  xargs默认的分隔符:空格或回车2.参数使用  想把所有.jpg文件删除,当然你可以 rm*.jpg,但是如果要递归操作所有子目录下的文件呢?  可以这样:find.-name"*.jpg"|xargsrm   这样,所有被find找到的文... 查看详情

xargs命令初了解

想检查下系统里用户的计划任务,百度了下,发现有个脚本命令对其中的xargs有点不台清楚,了解了下大概释义如下:xargs一般和管理配合使用,将前面管道结果分割成xargs后面所接命令的参数 查看详情

修改 xargs 中的替换字符串

...nginxargs【发布时间】:2012-06-0322:06:57【问题描述】:当我使用xargs时,有时我不需要显式使用替换字符串:find.-name"*.txt"|xargsrm-rf在其他情况下,我想指定替换字符串以执行以下操作:find.-name"*.txt"|xargs-I\'\'mv\'\'/foo/\'\'.bar前面的命... 查看详情

使用 xargs 将查找结果中的目录 mv 到另一个目录中

】使用xargs将查找结果中的目录mv到另一个目录中【英文标题】:Usexargstomvadirectoryfromfindresultsintoanotherdirectory【发布时间】:2012-12-0316:45:12【问题描述】:我有以下命令:find.-typed-mtime0-execmv/path/to/target-dir\\;这会将创建的目录移动... 查看详情

使用 xargs 和 awk 处理多个文件并将处理后的数据写入单独的文件

】使用xargs和awk处理多个文件并将处理后的数据写入单独的文件【英文标题】:Processseveralfileswithxargsandawkandwritetheprocesseddatatoseparatefiles【发布时间】:2016-06-1805:50:01【问题描述】:我有几个文件要使用awk处理,然后将awk的输出通... 查看详情

xargs 的最终论点

...】:我想做类似的事情:find.-typef|xargscpdest_dir但是xargs将使用dest_dir作为初始参数,而不是作为最终参数。我想知道:是否可以为xargs指定最终参数?还有其他方法可以达到同样的效果吗?编辑一个可能但麻烦的替代方案是:find.-... 查看详情

sh使用xargs更改所有文件和文件夹的权限(代码片段)

查看详情

sh使用grep和xargs批量搜索/编辑文件的示例(代码片段)

查看详情

xargs使用查询包含某字符串的所有文件

在initrd目录下,查找包含“Loadingvirtio.ko”的所有文件cdinitrdfind.|xargsgrep"Loadingvirtio.ko"若是想显示行号,可以如下:find.|xargsgrep-n "Loadingvirtio.ko"viinit来自为知笔记(Wiz) 查看详情

xargs命令教程(代码片段)

...但是常常被忽视,很多人不了解它的用法。本文介绍如何使用这个命令。一、标准输入与管道命令Unix命令都带有参数,有些命令可以接受"标准输入"(stdin)作为参数。$cat/etc/passwd|greproot上面的代码使用了管道命令(|)。管道命... 查看详情

如何在 xargs 命令中使用 &>>?

】如何在xargs命令中使用&>>?【英文标题】:Howtouse&>>inaxargscommand?【发布时间】:2017-11-1500:38:04【问题描述】:专家,按照这个question我执行这个命令:使用posix的xargs参数:find<somePath>-name\'*.html\'|sort-n|xargs-Ish-... 查看详情