Linux-命令-xargs
命令:xargs [options]
从标准输入(或者管道)获取数据,并将数据转换成命令行的参数
-I replace-str 大写I 可以指定表现形式,如{},[],()
Replace occurrences of replace-str in the initial-arguments with names read from standard input. Also,
unquoted blanks do not terminate input items; instead the separator is the newline character. Implies -x
and -L 1.
不加 -i 会出现以下问题
xargs -i选项在逻辑上用于接收传递的分批结果。
如果不使用-i,则默认是将分割后处理后的结果整体传递到命令的最尾部。但是有时候需要传递到多个位置,不使用-i就不知道传递到哪个位置了,例如重命名备份的时候在每个传递过来的文件名加上后缀.bak,这需要两个参数位。
使用xargs -i时以大括号{}作为替换符号,传递的时候看到{}就将被结果替换。可以将{}放在任意需要传递的参数位上,如果多个地方使用{}就实现了多个传递。
xargs -I(大写字母i)和xargs -i是一样的,只是-i默认使用大括号作为替换符号,-I则可以指定其他的符号、字母、数字作为替换符号,但是必须用引号包起来。man推荐使用-I代替-i,但是一般都图个简单使用-i,除非在命令中不能使用大括号,如touch {1..1000}.log时大括号就不能用来做替换符号。
例如下面的重命名备份过程。
[root@xuexi tmp]# ls logdir/
10.log 1.log 2.log 3.log 4.log 5.log 6.log 7.log 8.log 9.log
[root@xuexi tmp]# ls logdir/ | xargs -i mv ./logdir/{} ./logdir/{}.bak # 将分段传递到多个参数位 [root@xuexi tmp]# ls logdir/
10.log.bak 1.log.bak 2.log.bak 3.log.bak 4.log.bak 5.log.bak 6.log.bak 7.log.bak 8.log.bak 9.log.bak
但是我将“-i”选项划分在分批选项里,它默认一个段为一个批,每次传递一个批也就是传递一个段到指定的大括号{}位上。在稍后的分批选项优先级部分我会给出我的理由。
由于-i选项是按分段来传递的。所以尽管看上去等价的xargs echo和xargs -i echo {}并不等价。
[root@xuexi tmp]# ls | xargs echo
a b c d logdir one space.log shdir sh.txt test vmware-root
[root@xuexi tmp]# ls | xargs -i echo {}
a
b
c
d
logdir
one space.log
shdir
sh.txt
test
vmware-root
既然使用-i后是分段传递的,这就意味着指定了它就无法实现按批传递多个参数了;并且如果使用多个大括号,意味着必须使用-i,那么也无法分批传递。
例如,想将数字1-10每3个数显示在start和end之间。效果如下:
start 1 2 3 end
start 4 5 6 end
start 7 8 9 end
start 10 end
由于指定了参数传递位置,所以必须使用-i,那么就无法一次传递3个数。要解决这个问题,就要想办法让每三个数分一次段然后使用-i传递,方法也就随之而来了。可以将每三个数分一次行写入一个文件。如:
[root@xuexi tmp]# cat <<eof>logdir/1.log > 1 2 3 > 4 5 6 > 7 8 9 > 10 > eof
再使用xargs -i分批传递。
[root@xuexi tmp]# cat logdir/1.log | xargs -i echo "start {} end"
start 1 2 3 end
start 4 5 6 end
start 7 8 9 end
start 10 end
也可以使用多次xargs。很多时候无法解决分段的问题都可以通过多次使用xargs来解决。不过如果每次通过管道传递的数据量较大的话,这种方法性能就不怎么样了,毕竟每次管道传递都是需要消耗时间的。
[root@xuexi tmp]# echo {1..10} | xargs -n 3 | xargs -i echo "start {} end"