linux命令之-xargs超级管道
1、xagrs命令详解
1.1、命简单令介绍
- xargs - build and execute command lines from standard input,xargs 命令的作用,是将标准输入转为命令行参数,Unix 命令都带有参数,有些命令可以接受”标准输入”(
stdin
)作为参数。如:(cat /etc/passwd | grep root
)上面的代码使用了管道命令(|
)。管道命令的作用,是将左侧命令(cat /etc/passwd
)的标准输出转换为标准输入,提供给右侧命令(grep root
)作为参数。因为 grep 命令可以接受标准输入作为参数,所以上面的代码等同于下面的代码。(grep root /etc/passwd
),但是,大多数命令都不接受标准输入作为参数,只能直接在命令行输入参数,这导致无法用管道命令传递参数。举例来说,echo 命令就不接受管道传参。(echo "hello world" | echo
),上面的代码不会有输出。因为管道右侧的 echo 不接受管道传来的标准输入作为参数。
1.2、命令应用场景
- xargs 的作用在于,大多数命令(比如 rm、mkdir、ls )与管道一起使用时,都需要 xargs 将标准输入转为命令行参数,主要是将标准输入转为命令行参数;
1
2
3
4
5
6
7
8#如下的指令将管道左侧的标准输入,转为命令行参数 hello world,传给第二个 echo 命令。
[root@elk ~]# echo "hello world" | xargs echo
hello world
#如下的指令等同于 mkdir one two three。如果不加 xargs 就会报错,提示 mkdir 缺少操作参数。
[root@elk ~]# echo "one two three" | xargs mkdir -pv
mkdir: 已创建目录 "one"
mkdir: 已创建目录 "two"
mkdir: 已创建目录 "three"
2、xargs命令实战
2.1、命令帮助手册
1 | #NAME |
2.2、命令参数详解
-d
参数与分隔符1
2
3
4
5
6
7
8
9
10
11#默认情况下,xargs将换行符和空格作为分隔符,把标准输入分解成一个个命令行参数,而-d 参数可以更改分隔符;
#EXAMPLES-1:
[root@elk ~]# echo "wWwWw.lWiWsWiWrWlWiWfWe.WcWoWm" |xargs -dW
w w w.l i s i r l i f e. c o m
#EXAMPLES-2:
[root@elk ~]# echo -e "a\tb\tc"
a b c
[root@elk ~]# echo -e "a\tb\tc" | xargs -d "\t" echo
a b c
#上面的命令指定制表符 \t 作为分隔符,所以 a\tb\tc 就转换成了三个命令行参数。echo 命令的 -e 参数表示解释转义字符;-p
参数1
2
3
4
5
6
7
8#使用 xargs 命令以后,由于存在转换参数过程,有时需要确认一下到底执行的是什么命令;
#EXAMPLES-1:
[root@elk ~]# echo 'one two three' | xargs -p mkdir -pv
mkdir -pv one two three ?...y
mkdir: 已创建目录 "one"
mkdir: 已创建目录 "two"
mkdir: 已创建目录 "three"
#上面的命令执行以后,会打印出最终要执行的命令,让用户确认输入`y or Y`。用户按下回车以后,才会真正执行-t
参数1
2
3
4#-t 参数则是打印出最终要执行的命令,然后直接执行,不需要用户确认;
#EXAMPLES-1:
[root@elk ~]# echo 'one two three' | xargs -t rm -rf
rm -rf one two three-0
参数与find
命令1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35#由于 xargs 默认将空格作为分隔符,所以不太适合处理文件名,因为文件名可能包含空格。find 命令有一个特别的参数 -print0,指定输出的文件列表以 null 分隔。然后,xargs 命令的 -0 参数表示用 null 当作分隔符。
#EXAMPLES-1:
[root@localhost lisir]# ll
总用量 0
-rw-r--r-- 1 root root 0 9月 24 15:33 1
-rw-r--r-- 1 root root 0 9月 24 15:33 10 10
-rw-r--r-- 1 root root 0 9月 24 15:33 2
-rw-r--r-- 1 root root 0 9月 24 15:33 3
-rw-r--r-- 1 root root 0 9月 24 15:33 4
-rw-r--r-- 1 root root 0 9月 24 15:33 5
-rw-r--r-- 1 root root 0 9月 24 15:33 6
-rw-r--r-- 1 root root 0 9月 24 15:33 7
-rw-r--r-- 1 root root 0 9月 24 15:33 8
-rw-r--r-- 1 root root 0 9月 24 15:33 9
-rw-r--r-- 1 root root 0 9月 24 15:33 9 9
[root@localhost lisir]# find . -type f -print0 | xargs -0 -t -p rm -rf
rm -rf ./7 ./3 ./4 ./9 ./2 ./9 9 ./5 ./1 ./10 10 ./8 ./6 ?...
#上面命令删除当前路径下的所有文件。由于分隔符是 null,所以处理包含空格的文件名,也不会报;。
#EXAMPLES-2:
[root@localhost lisir]# find /tmp/lisir/ -type f -mtime -1 -print0 | xargs -0 -t tar -cvzf test.tar.gz
tar -cvzf test.tar.gz /tmp/lisir/7 /tmp/lisir/3 /tmp/lisir/4 /tmp/lisir/9 /tmp/lisir/2 /tmp/lisir/9 9 /tmp/lisir/5 /tmp/lisir/1 /tmp/lisir/10 10 /tmp/lisir/8 /tmp/lisir/6
[root@localhost lisir]# tar tvf test.tar.gz
-rw-r--r-- root/root 0 2019-09-24 15:33 tmp/lisir/7
-rw-r--r-- root/root 0 2019-09-24 15:33 tmp/lisir/3
-rw-r--r-- root/root 0 2019-09-24 15:33 tmp/lisir/4
-rw-r--r-- root/root 0 2019-09-24 15:33 tmp/lisir/9
-rw-r--r-- root/root 0 2019-09-24 15:33 tmp/lisir/2
-rw-r--r-- root/root 0 2019-09-24 15:33 tmp/lisir/9 9
-rw-r--r-- root/root 0 2019-09-24 15:33 tmp/lisir/5
-rw-r--r-- root/root 0 2019-09-24 15:33 tmp/lisir/1
-rw-r--r-- root/root 0 2019-09-24 15:33 tmp/lisir/10 10
-rw-r--r-- root/root 0 2019-09-24 15:33 tmp/lisir/8
-rw-r--r-- root/root 0 2019-09-24 15:33 tmp/lisir/6
#拓展:还有一个原因,使得 xargs 特别适合 find 命令。有些命令(比如 rm)一旦参数过多会报错 "参数列表过长",而无法执行,改用 xargs 就没有这个问题,因为它对每个参数执行一次命令;-L
指定行数传参数1
2
3
4
5
6
7#如果标准输入包含多行,-L 参数指定多少行作为一个命令行参数;
#EXAMPLES-1:
[root@localhost lisir]# echo -e "a\nb\nc" | xargs -L 1 echo
a
b
c
#上面代码指定每行运行一次 echo 命令,所以 echo 命令执行了三次,输出了三行;-n
参数1
2
3
4
5
6
7
8
9#-L 参数虽然解决了多行的问题,但是有时用户会在同一行输入多项;
#EXAMPLES-1:
[root@localhost lisir]# echo {0..9} | xargs -n 2 echo
0 1
2 3
4 5
6 7
8 9
#上面命令指定,每两个参数运行一次 echo 命令。所以,10 个阿拉伯数字运行了五次 echo 命令,输出了五行;-I
参数1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#如果 xargs 要将命令行参数传给多个命令,可以使用 -I 参数
#EXAMPLES-1:
[root@localhost lisir]# ls | egrep '1|2|3|4|5' | xargs -t -I {} mv {} {}.bak
mv 1 1.bak
mv 10 10 10 10.bak
mv 2 2.bak
mv 3 3.bak
mv 4 4.bak
mv 5 5.bak
#EXAMPLES-2:
[root@localhost lisir]# echo -e "one\ntwo\nthree" > lisir.txt
[root@localhost lisir]# cat lisir.txt
one
two
three
[root@localhost lisir]# cat lisir.txt | xargs -I file sh -c 'echo file; mkdir -pv file'
one
mkdir: 已创建目录 "one"
two
mkdir: 已创建目录 "two"
three
mkdir: 已创建目录 "three"
#上面代码中,lisir.txt 是一个三行的文本文件。我们希望对每一项命令行参数,执行两个命令(echo 和 mkdir),使用 -I file 表示 file 是命令行参数的替代字符串。执行命令时,具体的参数会替代掉 echo file; mkdir file 里面的两个 file-i
参数1
2
3
4
5
6
7
8#用 {} 代替 传递的数据
#EXAMPLES-1:
[root@localhost lisir]# ls | egrep '6|7|8|9' | xargs -t -i mv {} {}.bak
mv 6 6.bak
mv 7 7.bak
mv 8 8.bak
mv 9 9.bak
mv 9 9 9 9.bak--max-procs
参数1
2
3
4#xargs 默认只用一个进程执行命令。如果命令要执行多次,必须等上一次执行完,才能执行下一次。--max-procs 参数指定同时用多少个进程并行执行命令。--max-procs 2 表示同时最多使用两个进程,--max-procs 0 表示不限制进程数
#EXAMPLES-1:
[root@elk ~]# pgrep zabbix | xargs -n 1 --max-procs 0 kill
#上面命令表示,同时关闭所有zabbix进程,运行速度会快很多