Linux之xargs的用法

xargs 是 execute arguments 的缩写,它的作用是从标准输入中读取内容,并将此内容传递给它要协助的命令,并作为那个命令的参数来执行。

xargs是什么

xargs命令是给其他命令传递参数的一个过滤器,也是组合多个命令的一个工具。

为什么要用xargs

有时候我们的脚本却需要 echo ‘516’ | kill 这样的效果,例如 ps -ef | grep ‘test’ | kill 这样的效果,筛选出符合某条件的进程pid然后结束。这种需求对于我们来说是理所当然而且是很常见的,那么应该怎样达到这样的效果呢。有几个解决办法:

  1. 通过 kill ps -ef | grep 'ddd'
    这种形式,这个时候实际上等同于拼接字符串得到的命令,其效果类似于 kill $pid

  2. for procid in $(ps -aux | grep “some search” | awk ‘{print $2}’); do kill -9 $procid; done
    其实与第一种原理一样,只不过需要多次kill的时候是循环处理的,每次处理一个

  3. ps -ef | grep ‘ddd’ | xargs kill
    没错,这就是本文的主人公,xargs命令可以通过管道接受字符串,并将接收到的字符串通过空格分割成许多参数(默认情况下是通过空格分割) 然后将参数传递给其后面的命令,作为后面命令的命令行参数

xargs能做什么

它擅长将标准输入数据转换成命令行参数,xargs能够处理管道或者stdin并将其转换成特定命令的命令参数。

xargs也可以将单行或多行文本输入转换为其他格式,例如多行变单行,单行变多行。

xargs的默认命令是echo,空格是默认定界符。这意味着通过管道传递给xargs的输入将会包含换行和空白,不过通过xargs的处理,换行和空白将被空格取代。xargs是构建单行命令的重要组件之一。

xargs怎么用

xargs用作替换工具,读取输入数据重新格式化后输出,下面就给大家介绍一下怎么使用xargs。

xargs用法格式是这样的:

command | xargs -item  command

xargs与管道有什么不同

为了能够为大家解释清楚 xargs 和管道的关系,我们这次选用了更加典型的 cat 命令来为大家举例。

xargs与管道有什么不同呢,这是两个很容易混淆的东西,看了上面的xargs的例子还是有点云里雾里的话,我们来看下面的例子弄清楚为什么需要xargs:

[www.itselfstudy.cn]# echo '--help' | cat
--help

[www.itselfstudy.cn]# echo '--help' | xargs cat 
Usage: cat [OPTION]... [FILE]...
Concatenate FILE(s), or standard input, to standard output.

  -A, --show-all           equivalent to -vET
  -b, --number-nonblank    number nonempty output lines
  -e                       equivalent to -vE
  -E, --show-ends          display $ at end of each line
  -n, --number             number all output lines
....
# 省略后面内容

可以看到 echo ‘—help’ | cat 该命令输出的是echo的内容,也就是说将echo的内容当作cat处理的文件内容了,实际上就是echo命令的输出通过管道定向到cat的输入了。然后cat从其标准输入中读取待处理的文本内容。这等价于在test.txt文件中有一行字符 ‘—help’ 然后运行 cat test.txt 的效果。

而 echo ‘—help’ | xargs cat 等价于 cat —help 什么意思呢,就是xargs将其接受的字符串 —help 做成cat的一个命令参数来运行cat命令,同样 echo ‘test.c test.cpp’ | xargs cat 等价于 cat test.c test.cpp 此时会将test.c和test.cpp的内容都显示出来。

xargs参数选项

下面介绍一下xargs 后面的参数 -item 具体含义:

-a file 从文件中读入作为sdtin
-e flag ,注意有的时候可能会是-E,flag必须是一个以空格分隔的标志,当xargs分析到含有flag这个标志的时候就停止。
-p 当每次执行一个argument的时候询问一次用户。
-n num 后面加次数,表示命令在执行的时候一次用的argument的个数,默认是用所有的。
-t 表示先打印命令,然后再执行。
-i 或者是-I,这得看linux支持了,将xargs的每项名称,一般是一行一行赋值给 {},可以用 {} 代替。
-r no-run-if-empty 当xargs的输入为空的时候则停止xargs,不用再去执行了。
-s num 命令行的最大字符数,指的是 xargs 后面那个命令的最大命令行字符数。
-L num 从标准输入一次读取 num 行送给 command 命令。
-l 同 -L。
-d delim 分隔符,默认的xargs分隔符是回车,argument的分隔符是空格,这里修改的是xargs的分隔符。
-x exit的意思,主要是配合-s使用。。
-P 修改最大的进程数,默认是1,为0时候为as many as it can ,这个例子我没有想到,应该平时都用不到的吧。

示例

首先定义一个测试文件,内有多行文本数据:

[www.itselfstudy.cn]# 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

下面看一下使用xargs效果,单行输出:

[www.itselfstudy.cn]# 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

1. -n 选项多行输出:

[www.itselfstudy.cn]# cat test.txt | xargs -n3

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. -d 选项可以自定义一个定界符:

[www.itselfstudy.cn]# echo "nameXnameXnameXname" | xargs -dX

name name name name

结合-n选项使用:

[www.itselfstudy.cn]# echo "nameXnameXnameXname" | xargs -dX -n2

name name
name name

3. xargs的一个选项-I,使用-I指定一个替换字符串{},这个字符串在xargs扩展时会被替换掉,当-I与xargs结合使用,每一个参数命令都会被执行一次:

[www.itselfstudy.cn]# cat arg.txt | xargs -I {} ./sk.sh -p {} -l

-p aaa -l
-p bbb -l
-p ccc -l

4. 复制所有图片文件到 /data/images 目录下:

ls *.jpg | xargs -n1 -I cp {} /data/images

5. 假如你有一个文件包含了很多你希望下载的URL,你能够使用xargs下载所有链接:

cat url-list.txt | xargs wget -c

6. 查找所有的 jpg 文件,并且压缩它们:

find . -type f -name "*.jpg" -print | xargs tar -czvf images.tar.gz

7. 统计一个源代码目录中所有php文件的行数:

find . -type f -name "*.php" -print0 | xargs -0 wc -l

8. 查找系统中的每一个普通文件,然后使用xargs命令来测试他们分别属于哪类文件

find . -type f -print | xargs file

9. 在整个系统中查找内存信息存储文件(core dump),然后把结果保存到/tmp/core.log文件中

find / -name "core" -print | xargs echo "" > /tmp/core.log

10. 在当前目录下查找所有用户具有读、写和执行权限的文件。并收回相应的写权限

find . -perm -7 -print | xargs chmod o-w

11. 用grep命令在所有的普通文件中搜索hostname这个词

find . -type f -print | xargs grep "hostname"

12. 用grep命令在当前目录下的所有普通文件中搜索hostnames这个词

find . -name * -type f -print | xargs grep "hostnames"
# \用来取消find命令中的*在shell中的特殊含义

13. 使用xargs执行mv

find . -name "*.log" | xargs -i mv {} test4

14. find后执行xargs提示xargs:argument line too long解决方法:

find . -type f -atime +0 -printf0 | xargs -0 -11 -t rm -f
find . -type f -atime +0 -print0 | xargs -0 -l1 -t rm -f

-l1是一次处理一个;-t是处理之前打印出命令

15. xargs的-p参数的使用

find . -name "*.log" | xargs -p -i mv {} ..

-p参数会提示让你确认是否执行后面的命令,y执行,n不执行。

16. 删除 /home/omc/ftl/下的log文件

ll *.log |xargs rm -rf {}     #【错误】
rm: invalid option -- 'w'     ll 不能删除、复制
Try 'rm --help' for more information.

ls *.log |xargs rm -rf {}     #【正确】

17. 在当前目录下查找所有用户权限644的文件,并更改权限600

find /home/omc/ftl -perm 644 | xargs chmod 600

18. -E 选项,有的系统的xargs版本可能是-e eof-str
该选项指定一个字符串,当xargs解析出多个命令行参数的时候,如果搜索到-e指定的命令行参数,则只会将-e指定的命令行参数之前的参数(不包括-e指定的这个参数)传递给xargs后面的命令

echo '11 22 33' | xargs -E '33' echo
# 输出:11 22

注意:-E只有在xargs不指定-d的时候有效,如果指定了-d则不起作用,而不管-d指定的是什么字符,空格也不行

echo '11 22 33' | xargs -d ' ' -E '33' echo 
# 输出 11 22 33
echo '11@22@33@44@55@66@77@88@99@00 aa 33 bb' | xargs -E '33' -d '@' -p  echo
# 输出 11 22 33 44 55 66 77 88 99 00 aa 33 bb

参考文献:
https://www.runoob.com/linux/linux-comm-xargs.html
https://www.cnblogs.com/wangqiguo/p/6464234.html#_label0

1000

GS

北京 | php攻城狮

创作 35 粉丝 2

fighting