前言
在日常的Linux使用中,我们经常需要使用到管道符 “|” 进行命令连接,来处理组合操作,例如:
[root@test ~]# 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 [root@test ~]# netstat -anlpt | grep -i estab | wc -l 245 [root@test ~]#
管道符的操作是将前一个命令执行后的正确输出作为后一个命令的操作对象执行。
这样的操作可以胜任绝大多数操作环境,但如果是要将前一个命令的正确输出作为后一个命令的参数来执行,有时就显得力不从心了,例如:
[root@test tmp]# touch f1 f2.log [root@test tmp]# mkdir bd [root@test tmp]# ls | grep -E .log$ | cp bd/ cp: missing destination file operand after ‘bd/’ Try 'cp --help' for more information. [root@test tmp]#
本欲将.log结尾的文件拷贝至bd/目录下,但操作却是bd/为拷贝源,而f2.log则为目的,执行失败。可见作为后一个命令的操作对象是放在结尾执行的。
之所说说是操作对象,而不参数,如下操作便可看出来:
[root@test tmp]# ps -ef | awk '/dubbo/ &&!/awk/ {print $2}' 3009 [root@test tmp]# ps -ef | awk '/dubbo/ &&!/awk/ {print $2}' | kill -9 kill: usage: kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l [sigspec] [root@test 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] [server_id@]<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 [root@test tmp]#
要想让结果作为参数来使用,有多种操作方法,如使用循环:
[root@test 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 [root@test tmp]#
但这样稍显复杂,所以下面介绍下xargs命令。
xargs
xargs是一条Unix和类Unix操作系统的常用命令。它的作用是将参数列表转换成小块分段传递给其他命令,以避免参数列表过长的问题。xargs能够处理管道或者stdin并将其转换成特定命令的命令参数。xargs也可以将单行或多行文本输入转换为其他格式,例如多行变单行,单行变多行。xargs的默认命令是echo,空格是默认定界符。xargs是构建单行命令的重要组件之一。
xargs命令用法:
- xargs用作替换工具,读取输入数据重新格式化后输出。
[root@test 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 [root@test 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 [root@test tmp]#
-n选项,指定每行最大参数个数:
[root@test 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 [root@test tmp]#
-d,–delimiter=选项,指定分隔符:
[root@test tmp]# echo "testZTestZtEstZtesT" | xargs -d Z test Test tEst tesT [root@test tmp]#
结合-n一起使用:
[root@test tmp]# echo "testZTestZtEstZtesT" | xargs -d Z -n 2 test Test tEst tesT [root@test tmp]#
- 读取stdin,将格式化后的参数传递给下一个命令
[root@test 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 [root@test tmp]#
默认从stdin中获取的值都是作为参数放在后一个命令的,xargs有选项可以使用替换字符串,在xargs扩展时会被替换掉。
-I选择,需指定扩展字符串:[root@test 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 [root@test 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 [root@test tmp]#
-i,–replace选项,同-I{},替换字符串即为{},此选项将会弃用:
[root@test 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 [root@test 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 [root@test tmp]#
此功能,就可以满足我们一开始的需求:
[root@test tmp]# tree . . ├── bd ├── f1 ├── f2.log └── testfile 1 directory, 3 files [root@test tmp]# ls | grep -E *.log$ | xargs -I{} mv {} bd/ [root@test tmp]# tree . . ├── bd │ └── f2.log ├── f1 └── testfile 1 directory, 3 files [root@test tmp]#
- xargs结合find使用
使用rm删除指定文件:[root@test tmp]# rm `find /data/ -type f` -bash: /usr/bin/rm: Argument list too long [root@test tmp]#
当要删除的文件太多时,就会因为“参数列表过长”错误而无法执行,使用xargs可避免这种问题(所有删除操作都谨慎使用,会无提示直接删除!!!):
[root@test tmp]# find /data/ -type f -print0 | xargs -0 rm [root@test tmp]# mv f1 f1.log [root@test tmp]# find ./ -name "*.log" -print0 ./bd/f2.log./f1.log[root@test tmp]# find ./ -name "*.log" -print0 | xargs -0 ./bd/f2.log ./f1.log [root@test tmp]#
示例中xargs将find产生的长串文件列表拆散成多个子串,然后对每个子串调用rm。-print0表示输出以null分隔(-print使用换行);-0表示输入以null分隔。这样要比上如下使用find命令效率高的多。
[root@test tmp]# find /data/ -type f -exec rm -rf {} \;
上面这条命令会对每个文件调用”rm”命令。当然使用新版的”find”也可以得到和”xargs”命令同样的效果:
[root@test tmp]# find /data/ -type f -exec rm '{}' +
查找目录中所有图片并压缩它们:
[root@test tmp]# find . -type f -name "*.jpg" -print | xargs tar -czvf images.tar.gz