我们可以用管道将stdout重定向到另一个命令的stdin。例如:
cat foo.txt | grep "test"
但是,有些命令只能以命令行参数的形式接受数据,而无法通过stdin接受数据流。
这时候xargs就派上用场了。xargs能够处理stdin并将其转换为特定命令的命令行参数。xargs也可以将单行或多行文本输入转换成其他格式,比如单行变多行或者多行变单行。
xargs命令应该紧跟在管道操作符之后,以标准输入作为主要的源数据流。xargs使用stdin并通过提供命令行参数来执行其他命令。
将多行输入转换成单行输出:
root@debian:/home/chicol/scripts/chapter_2# cat example.txt
1 2 3 4 5 6
7 8 9 10
11 12
root@debian:/home/chicol/scripts/chapter_2# cat example.txt | xargs
1 2 3 4 5 6 7 8 9 10 11 12
将当行输入转换成多行输出:
root@debian:/home/chicol/scripts/chapter_2# cat example.txt | xargs -n 3
1 2 3
4 5 6
7 8 9
10 11 12
root@debian:/home/chicol/scripts/chapter_2#
xargs可以使用制定的定界符分隔参数:
用法:用-d选项为输入指定一个定制的定界符
root@debian:/home/chicol/scripts/chapter_2# echo "splitXsplitXsplitXsplitXsplit" | xargs -d X
split split split split split
1. 读取stdin,将格式化参数传递给命令
这里有个小程序cecho.sh,当参数传递给文件cecho.sh后,它会将这些参数打印出来,并以#字符作为结尾。#!/bin/bash
# FileName: cecho.sh
echo $* '#'
root@debian:/home/chicol/scripts/chapter_2# ./cecho.sh arg1 arg2
arg1 arg2 #
现在有一个名为args.txt的参数列表文件,内容如下:
root@debian:/home/chicol/scripts/chapter_2# cat args.txt
arg1
arg2
arg3
1)执行./cecho.sh,每次使用1个参数:
root@debian:/home/chicol/scripts/chapter_2# cat args.txt | xargs -n 1 ./cecho.sh
arg1 #
arg2 #
arg3 #
2)执行./cecho.sh,每次使用2个参数:
root@debian:/home/chicol/scripts/chapter_2# cat args.txt | xargs -n 2 ./cecho.sh
arg1 arg2 #
arg3 #
3)执行./cecho.sh,执行命令时一次提供所有的参数
root@debian:/home/chicol/scripts/chapter_2# cat args.txt | xargs ./cecho.sh
arg1 arg2 arg3 #
在上面的例子中,我们直接为特定的命令提供命令行参数。这些参数都来自args.txt。但实际上除了它们外,我们还需要
一些固定不变的命令参数。如下例子:
./cecho -p arg1 -l #arg1是唯一可变的参数,其他参数保持不变。
那么我们可以使用xargs的选项"-I"来完成这个操作
root@debian:/home/chicol/scripts/chapter_2# cat args.txt | xargs -I {} ./cecho.sh -p {} -l
-p arg1 -l #
-p arg2 -l #
-p arg3 -l #
-I指定了替换字符串。对于每一个命令参数,字符串{}都会被从stdin读取到的参数替换掉。
3. find与xargs结合使用
find . -type f -name "*.txt" -print0 | xargs -0 rm -f
这里-print0表示以字符null('\0')来分隔输出,xargs -0 将\0作为输入定界符。
4. 结合stdin,巧用while语句和子shell
xargs只能以有限的几种方式来提供参数,而且它也不能为多组命令提供参数。要执行包含来自标准输入的多个参数的命令,有一种
非常灵活的方法。包含while循环的子shell可以用来读取参数,然后通过一种巧妙的方式执行命令:
$ cat files.txt | ( while read arg; do cat $arg; done )
#等同于cat files.txt | xargs -I {} cat {}
这里的while循环中,可以将cat $arg替换成任意数量的命令,这样我们就可以对同一个参数执行多条命令。
Note:子shell操作符内部的多个命令可以作为一个整体来运行:
$ cmd0 | ( cmd1; cmd2; cmd3 ) | cmd4
如果cmd1是cd /,那么它会改变子shell的工作目录,但是改变仅限于子shell内部。cmd4则完全不知道工作目录发生了变化
阅读(1041) | 评论(0) | 转发(0) |