xargs命令使用

前言

在日常的Linux使用中,我们经常需要使用到管道符 “|” 进行命令连接,来处理组合操作,例如:

[[email protected] ~]# ifconfig | grep -iw inet 
        inet 172.16.220.192  netmask 255.255.255.0  broadcast 172.16.220.255
        inet 127.0.0.1  netmask 255.0.0.0
[[email protected] ~]# netstat -anlpt | grep -i estab | wc -l
245
[[email protected] ~]#

管道符的操作是将前一个命令执行后的正确输出作为后一个命令的操作对象执行。

这样的操作可以胜任绝大多数操作环境,但如果是要将前一个命令的正确输出作为后一个命令的参数来执行,有时就显得力不从心了,例如:

[[email protected] tmp]# touch f1 f2.log
[[email protected] tmp]# mkdir bd
[[email protected] tmp]# ls | grep -E .log$ | cp bd/
cp: missing destination file operand after ‘bd/’
Try 'cp --help' for more information.
[[email protected] tmp]#

本欲将.log结尾的文件拷贝至bd/目录下,但操作却是bd/为拷贝源,而f2.log则为目的,执行失败。可见作为后一个命令的操作对象是放在结尾执行的。

之所说说是操作对象,而不参数,如下操作便可看出来:

[[email protected] tmp]# ps -ef | awk '/dubbo/ &&!/awk/ {print $2}'                   
3009
[[email protected] tmp]# ps -ef | awk '/dubbo/ &&!/awk/ {print $2}' | kill -9
kill: usage: kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l [sigspec]
[[email protected] tmp]# ps -ef | awk '/dubbo/ &&!/awk/ {print $2}' | jmap
Usage:
    jmap [option] <pid>
        (to connect to running process)
    jmap [option] <executable <core>
        (to connect to a core file)
    jmap [option] [[email protected]]<remote server IP or hostname>
        (to connect to remote debug server)

where <option> is one of:
    <none>               to print same info as Solaris pmap
    -heap                to print java heap summary
    -histo[:live]        to print histogram of java object heap; if the "live"
                         suboption is specified, only count live objects
    -permstat            to print permanent generation statistics
    -finalizerinfo       to print information on objects awaiting finalization
    -dump:<dump-options> to dump java heap in hprof binary format
                         dump-options:
                           live         dump only live objects; if not specified,
                                        all objects in the heap are dumped.
                           format=b     binary format
                           file=<file>  dump heap to <file>
                         Example: jmap -dump:live,format=b,file=heap.bin <pid>
    -F                   force. Use with -dump:<dump-options> <pid> or -histo
                         to force a heap dump or histogram when <pid> does not
                         respond. The "live" suboption is not supported
                         in this mode.
    -h | -help           to print this help message
    -J<flag>             to pass <flag> directly to the runtime system
[[email protected] tmp]#

要想让结果作为参数来使用,有多种操作方法,如使用循环:

[[email protected] tmp]# ps -ef | awk '/dubbo/ &&!/awk/ {print $2}' | while read line ;do jmap $line;done
Attaching to process ID 3009, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 24.80-b11
0x0000000000400000      7K      /usr/local/jdk1.7.0_80/jre/bin/java
0x00007f5a93797000      66K     /usr/lib64/libbz2.so.1.0.6
0x00007f5a939a7000      153K    /usr/lib64/liblzma.so.5.2.2
0x00007f5a93bcd000      114K    /usr/local/lib/libz.so.1.2.11
0x00007f5a93de8000      97K     /usr/lib64/libelf-0.166.so
0x00007f5a980f1000      19K     /usr/lib64/libattr.so.1.1.0
0x00007f5a982f6000      294K    /usr/lib64/libdw-0.166.so
0x00007f5a9853e000      19K     /usr/lib64/libcap.so.2.22
0x00007f5a98743000      108K    /usr/lib64/libresolv-2.17.so
0x00007f5a9895d000      27K     /usr/lib64/libnss_dns-2.17.so
0x00007f5a9b16f000      86K     /usr/lib64/libgcc_s-4.8.5-20150702.so.1
0x00007f5a9b385000      250K    /usr/local/jdk1.7.0_80/jre/lib/amd64/libsunec.so
0x00007f5a9b6cd000      44K     /usr/local/jdk1.7.0_80/jre/lib/amd64/libmanagement.so
0x00007f5a9b8d5000      113K    /usr/local/jdk1.7.0_80/jre/lib/amd64/libnet.so
0x00007f5a9baec000      89K     /usr/local/jdk1.7.0_80/jre/lib/amd64/libnio.so
0x00007f5aa006c000      64K     /usr/lib64/libnss_myhostname.so.2
0x00007f5aa9bfe000      107K    /usr/local/jdk1.7.0_80/jre/lib/amd64/libzip.so
0x00007f5aa9e16000      60K     /usr/lib64/libnss_files-2.17.so
0x00007f5aaa029000      214K    /usr/local/jdk1.7.0_80/jre/lib/amd64/libjava.so
0x00007f5aaa254000      63K     /usr/local/jdk1.7.0_80/jre/lib/amd64/libverify.so
0x00007f5aaa462000      43K     /usr/lib64/librt-2.17.so
0x00007f5aaa66a000      1115K   /usr/lib64/libm-2.17.so
0x00007f5aaa96c000      14879K  /usr/local/jdk1.7.0_80/jre/lib/amd64/server/libjvm.so
0x00007f5aab7e6000      2068K   /usr/lib64/libc-2.17.so
0x00007f5aabba7000      19K     /usr/lib64/libdl-2.17.so
0x00007f5aabdab000      96K     /usr/local/jdk1.7.0_80/jre/lib/amd64/jli/libjli.so
0x00007f5aabfc0000      140K    /usr/lib64/libpthread-2.17.so
0x00007f5aac1dc000      151K    /usr/lib64/ld-2.17.so
[[email protected] tmp]#

但这样稍显复杂,所以下面介绍下xargs命令。

xargs

xargs是一条Unix和类Unix操作系统的常用命令。它的作用是将参数列表转换成小块分段传递给其他命令,以避免参数列表过长的问题。xargs能够处理管道或者stdin并将其转换成特定命令的命令参数。xargs也可以将单行或多行文本输入转换为其他格式,例如多行变单行,单行变多行。xargs的默认命令是echo,空格是默认定界符。xargs是构建单行命令的重要组件之一。

xargs命令用法:

  • xargs用作替换工具,读取输入数据重新格式化后输出。
    [[email protected] tmp]# cat testfile 
    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
    [[email protected] tmp]# cat testfile | 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
    [[email protected] tmp]#

    -n选项,指定每行最大参数个数:

    [[email protected] tmp]# cat testfile | xargs -n 3
    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
    [[email protected] tmp]#

    -d,–delimiter=选项,指定分隔符:

    [[email protected] tmp]# echo "testZTestZtEstZtesT" | xargs -d Z
    test Test tEst tesT
    
    [[email protected] tmp]#

    结合-n一起使用:

    [[email protected] tmp]# echo "testZTestZtEstZtesT" | xargs -d Z -n 2
    test Test
    tEst tesT
    
    [[email protected] tmp]#
  • 读取stdin,将格式化后的参数传递给下一个命令
    [[email protected] tmp]# echo "127.0.0.1" | xargs ping -c 1
    PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
    64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.028 ms
    
    --- 127.0.0.1 ping statistics ---
    1 packets transmitted, 1 received, 0% packet loss, time 0ms
    rtt min/avg/max/mdev = 0.028/0.028/0.028/0.000 ms
    [[email protected] tmp]#

    默认从stdin中获取的值都是作为参数放在后一个命令的,xargs有选项可以使用替换字符串,在xargs扩展时会被替换掉。
    -I选择,需指定扩展字符串:

    [[email protected] tmp]# cat testfile | xargs -I {} echo {} -l
    a b c d -l
    e f g h i -l
    j k l m -l
    n o p -l
    q r s -l
    t u v w -l
    x y z -l
    [[email protected] tmp]# cat testfile | xargs -I [] echo [] -l
    a b c d -l
    e f g h i -l
    j k l m -l
    n o p -l
    q r s -l
    t u v w -l
    x y z -l
    [[email protected] tmp]#

    -i,–replace选项,同-I{},替换字符串即为{},此选项将会弃用:

    [[email protected] tmp]# cat testfile | xargs -i echo {} -l
    a b c d -l
    e f g h i -l
    j k l m -l
    n o p -l
    q r s -l
    t u v w -l
    x y z -l
    [[email protected] tmp]# cat testfile | xargs --replace echo {} -l  
    a b c d -l
    e f g h i -l
    j k l m -l
    n o p -l
    q r s -l
    t u v w -l
    x y z -l
    [[email protected] tmp]#

    此功能,就可以满足我们一开始的需求:

    [[email protected] tmp]# tree .
    .
    ├── bd
    ├── f1
    ├── f2.log
    └── testfile
    
    1 directory, 3 files
    [[email protected] tmp]# ls | grep -E *.log$ | xargs -I{} mv {} bd/
    [[email protected] tmp]# tree .
    .
    ├── bd
    │   └── f2.log
    ├── f1
    └── testfile
    
    1 directory, 3 files
    [[email protected] tmp]#
  • xargs结合find使用
    使用rm删除指定文件:

    [[email protected] tmp]# rm `find /data/ -type f`
    -bash: /usr/bin/rm: Argument list too long
    [[email protected] tmp]#

    当要删除的文件太多时,就会因为“参数列表过长”错误而无法执行,使用xargs可避免这种问题(所有删除操作都谨慎使用,会无提示直接删除!!!):

    [[email protected] tmp]# find /data/ -type f -print0 | xargs -0 rm
    [[email protected] tmp]# mv f1 f1.log
    [[email protected] tmp]# find ./ -name "*.log" -print0
    ./bd/f2.log./f1.log[[email protected] tmp]# find ./ -name "*.log" -print0 | xargs -0
    ./bd/f2.log ./f1.log
    [[email protected] tmp]#

    示例中xargs将find产生的长串文件列表拆散成多个子串,然后对每个子串调用rm。-print0表示输出以null分隔(-print使用换行);-0表示输入以null分隔。这样要比上如下使用find命令效率高的多。

    [[email protected] tmp]# find /data/ -type f -exec rm -rf {} \;

    上面这条命令会对每个文件调用”rm”命令。当然使用新版的”find”也可以得到和”xargs”命令同样的效果:

    [[email protected] tmp]# find /data/ -type f -exec rm '{}' +

    查找目录中所有图片并压缩它们:

    [[email protected] tmp]# find . -type f -name "*.jpg" -print | xargs tar -czvf images.tar.gz

留下评论

error: Content is protected !!