[youngyoung tmp]$ seq 1 5
1
2
3
4
5
[youngyoung tmp]$ seq 1 5 | xargs
1 2 3 4 5
[youngyoung tmp]$ seq 1 5 | xargs -n 2
1 2
3 4
5
[youngyoung tmp]$
1. 为什么需要xargs命令
1.1 管道|的缺陷
管道实现的是将前面的输出stdout作为后面的输入stdin,但是有些命令不接受管道的传递方式。例如:ls,这是为什么呢?
因为有些命令希望管道传递过来的是参数,但是直接使用管道有时无法传递到命令的参数位。这时候就需要xargs,xargs实现的是将管道传递过来的stdin进行处理然后传递到命令的参数位置上。
也就是xargs完成了两个行为:
- 1. 处理管道传输过来的stdin;
- 2. 将处理后的数据传递到正确的位置;
1.2 xargs对数据的处理
处理大量数据的时候,可能会发生参数列表过长的情况,而xargs将完成参数的定位,但是xrags如何处理管道传输的stdin呢?
其实就是完成两个操作:
- 1. 对数据的分割;
- 2. 对数据的分批;
xargs处理的优先级或顺序:先分割,在分批,然后传递到参数位。
1.2.1 xrags的并发处理
但需要注意的是,尽管实现了分批处理,但是默认情况下并没有提高任何效率,因为分批传递之后还是一次执行一个。而且有时候分批之后是将其作为一个参数的整体,并不会将分批中的信息分段执行。
事实上,xargs提供了-P选项,用于指定并发执行的数量(默认是只要一个处理进程,不会提供效率,但是可以指定为N个子进程,或者指定为0表示尽可能多的利用CPU)。这样就能将让分批操作更好的利用多核CPU,从而提升效率。例如上面分成了两批,指定-P 2可以并发执行两批,而并非执行完第一批之后再执行第二批。
2. xrags的分割行为
xargs命令会将接收的stdin所有的空白(空格、制表符、换行符)都转换为空格。我们使用xargs -d "xx"自定义规则对数据进行切分。默认情况下,xargs使用空格来切分数据。
3. xargs的分批行为
4 xargs -i 接收传递的分批结果
如果不使用
-i
,则默认是将分割处理
后的结果整体传递到【命令的最尾部】。但是有时候需要传递到多个位置,不使用-i
就不知道传递到哪个位置了。
例如:重命名备份的时候在每个传递过来的文件名加上后缀.bak,这需要两个参数位。
语法:
使用xargs -i时以大括号{}作为替换符号,传递的时候看到{}就将结果替换,可以将{}放在任意需要传递的参数位置上。如果多个地方使用{}就实现了多个传递。
xargs -I和xargs -i是一样的,只是-i默认使用大括号作为替换符号,-I可以指定其他符号、字母、数字作为替换符号,但是必须用引号包起来。man推荐使用-I代替-i,但是一般使用-i方便,除非在命令中不能使用{},例如touch {1...10}.log时,大括号就不能用来做替换符号。
分析:重命名备份的时候在每个传递过来的文件名加上后缀.bak。
案例分析1:
【./指的是当前目录】
重命名逻辑是:mv ./logdir/a.log ./logdir/a.log.bak
我们想将一个目录下的文件都要执行某些逻辑。
命令:ls logdir/ | xargs -i mv ./logdir/{} ./logdir/{}.bak
为什么将“-i”选项划分在分批选项里面,因为它默认一个段就是一个批,每次传递一个批就是传递一个段到指定大括号{}位上。不理解,可以看下1.2.4 分批选项的生效规则
案例分析2:
例如:想将数字1-10没三个数显示在start和end之间。
start 1 2 3 end
start 4 5 6 end
start 7 8 9 end
start 10 end
5. 分批选项的生效规则
-i、-L、-n选项都是分批选项,他们的生效规则是:谁指定在后面,谁就生效!!!
-i在-n之后,-n将被忽略
实际上,-i就是隐含了-L 1,-i是分批并传递这两个作用跟严格些。