linux命令之-xargs超级管道

linux命令之-xargs超级管道

1、xagrs命令详解

1.1、命简单令介绍

image_1dlhn08g81asfmcf1h541dc81b7mm.png-619.7kB

  • 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
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#NAME
xargs - build and execute command lines from standard input

#SYNOPSIS
xargs [-0prtx] [-E eof-str] [-e[eof-str]] [--eof[=eof-str]] [--null] [-d delimiter] [--delimiter delimiter] [-I replace-str] [-i[replace-str]] [--replace[=replace-str]] [-l[max-lines]] [-L max-lines] [--max-lines[=max-lines]] [-n max-
args] [--max-args=max-args] [-s max-chars] [--max-chars=max-chars] [-P max-procs] [--max-procs=max-procs] [--interactive] [--verbose] [--exit] [--no-run-if-empty] [--arg-file=file] [--show-limits] [--version] [--help] [command [initial-
arguments]]

#DESCRIPTION
This manual page documents the GNU version of xargs. xargs reads items from the standard input, delimited by blanks (which can be protected with double or single quotes or a backslash) or newlines, and executes the command (default is
/bin/echo) one or more times with any initial-arguments followed by items read from standard input. Blank lines on the standard input are ignored.
Because Unix filenames can contain blanks and newlines, this default behaviour is often problematic; filenames containing blanks and/or newlines are incorrectly processed by xargs. In these situations it is better to use the -0 option,
which prevents such problems. When using this option you will need to ensure that the program which produces the input for xargs also uses a null character as a separator. If that program is GNU find for example, the -print0 option
does this for you.
If any invocation of the command exits with a status of 255, xargs will stop immediately without reading any further input. An error message is issued on stderr when this happens.

#OPTIONS(仅贴出主要使用参数进行翻译)
-0 由于 xargs 默认将空格作为分隔符,所以不太适合处理文件名,因为文件名可能包含空格。find 命令有一个特别的参数 -print0,指定输出的文件列表以 null 分隔。然后,xargs 命令的 -0 参数表示用 null 当作分隔符。

-d delim
为输入指定一个定制的分割符,默认情况下,xargs将换行符和空格作为分隔符,把标准输入分解成一个个命令行参数,-d 参数可以更改分隔符(echo "wWwWw.WbWaWiWdWuW.WcWoWm" |xargs -dW)

--help Print a summary of the options to xargs and exit.

-I replace-str
用string来代替传递的数据-n[数字] 设置每次传递几行数据

-i[replace-str]
用{}代替 传递的数据

-L max-lines
如果标准输入包含多行,-L 参数指定多少行作为一个命令行参数

-n max-args
-L 参数虽然解决了多行的问题,但是有时用户会在同一行输入多项,-n 参数指定每次将多少项作为命令行参数。

-p 使用 xargs 命令以后,由于存在转换参数过程,有时需要确认一下到底执行的是什么命令。-p 参数打印出要执行的命令,询问用户是否要执行 ‘y’ or ‘Y’.

-s max-chars
[大小] 设置传递参数的最大字节数(小于131072字节)

--verbose
-t -t 参数则是打印出最终要执行的命令,然后直接执行,不需要用户确认。

--version
Print the version number of xargs and exit.

-P max-procs
xargs 默认只用一个进程执行命令。如果命令要执行多次,必须等上一次执行完,才能执行下一次。--max-procs 参数指定同时用多少个进程并行执行命令。--max-procs 2 表示同时最多使用两个进程,--max-procs 0 表示不限制进程数。

#EXAMPLES(实列)
#假如你有一个文件包含了很多你希望下载的URL, 你能够使用xargs 下载所有链接
cat list.txt | xargs wget –c

#查找所有的jpg 文件,并且压缩它
find / -name *.jpg -type f -print | xargs tar -cvzf images.tar.gz

#删除该目录下面的普通文件
find ./ -type f -print0 | xargs -0 rm
find -name '.svn' |xargs rm -rf

#将当前目录下php文件,改名字
ls | grep .php | xargs -i mv {} {}.bak

#与上例相同
ls | grep .php | xargs -I {} mv {} {}.bak

#删除当前文件夹下的,tmp文件
find ./ -name "*.tmp" | xargs -i rm -rf {}

#将包含mem的文件并把移到指定的目录里,用户需确认是否执行
ls *mem* |xargs -i -p mv {} sky/

#批量拷贝文件夹到指定目录
for i in `find . -name *.html`;do j=${i%/*/*};cp -rfp $i $j;done

#批量将当前目录下属主为root的所有类型文件,修改用户信息为www:nfsnobody
find . -user root | xargs -i chown www:nfsnobody {}

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进程,运行速度会快很多
-------------本文结束感谢您的阅读-------------
LiGuanCheng wechat
如有问题,请与我微信交流或通过右下角“daovoice”与我联系~。
请我喝一杯咖啡~