我们可以利用管道将一个命令的stdout重定向到另一个命令的stdin

cat foo.txt|grep “test”

但是有些命令只能以命令行参数的形式接受数据,无法通过stdin接受数据流,在这种情况下,我们没法使用管道来提供那些只有通过命令行参数才能提供的数据

xargs是一个很好用的命令,可以将标准输入数据转换为命令行参数,xargs能够处理stdin并将其转换为特定命令的命令行参数,xargs可以将单行或者多行文本输入转换为其他格式

对于一些单行命令,使用管道符| 连接起来的,就需要xargs来进行构建

我们在使用xargs命令的时候,需要以标准输入作为主要的源数据流,并且使用stdin通过提供命令行参数来执行其他命令

xargs是一个种替换方式,类似find中的-exec

常见的xargs使用方式

将多行输入转换为单行的输出

只需要将换行符移除,并且使用 ” ” 空格进行替换,就可以实现多行输入的转换, ‘\n’被解释为一个换行符,换行符就是多行文本之间的定界符,利用xargs,可以用空格替换掉换行符,这样就可以将多行文本转为了单行文本

图片

或者将单行输入变为多行输出

指定每一行最大的参数数量 n 可以将任何来自stdin的文本划分为多行,每行n个参数,然后利用 ” “来隔开

图片

还可以利用 -d 来进行定界符设置

echo “splitXsplitXsplitXsplit” | xargs -d X

split split split split

利用-d将X作为定界符,我们指定了X作为输入定界符,默认情况下,xargs采用内部字段分隔符 IFS

作为定界符

在了解完了如何使用xargs将stdin格式化为不同输出形式以作为参数,现在,我们来学习如何将这些参数传递给命令

1.比如,我们有一个如下的格式化参数

图片

这个sh的功能是将输入的参数打印出来,后面加上了 #

有一个包含着参数列表的文件,我们需要将这些参数传给这个sh

文件如下

图片

我们可以利用xargs将这个命令执行多次

cat args.txt | xargs -n 1 ./cecho.sh

arg1 #

arg2 #

arg3 #

每次执行需要X个参数的命令时候,使用

INPUT | xargs -n X

或者一口气只执行一次,但是输入所有的参数

cat args.txt | xargs ./cecho.sh

arg1 arg2 arg3 #

我们为特定的命令提供了命令行参数

但是如果有一些需要固定格式不变的命令参数,就需要思考使用下面的命令格式

例如

./cecho.sh -p arg1 -l

应对这种需求的使用,我们可以使用xargs -I的选项

cat args.txt | xargs -I {} ./cecho,sh -p {} -l

-I { } 指定了替换字符串,对于每一个命令参数,字符串{} 会被从 stdin读取到的参数替换

比如如下的使用命令

echo “splitXsplitXsplitXsplit” | xargs -d X| xargs -I  {} echo {}

-I 使得命令就好比在一个循环中执行一样,如果有三个参数,就会连带着{}替换被执行三次

使用find来配合xargs

一般来说,两者的结合使用为 find . -type f -name “*.txt” -print | xargs rm -f

但是会存在一些风险,因为有些文件的文件名中带有空格,导致输出的结果中无法判断究竟是 ‘\n’还是 ‘ ‘ 导致会被误删除 比如 hell text.txt 会被当成 hell 和 text.txt

所以,最好还是print0和find相结合使用

这样,最终的使用方式就是

find .-type f -name “*.txt” -print0 | xargs -0 rm -f

统计目录中所有文件的行数

例如,统计所有txt文件的行数

find source_code_dir_path -type f -name “*.txt” -print0 | xargs -0 wc -l

图片

结合stdin,巧妙的运用while语句和子shell

xargs只能有几种常见的输出方式,也不能为多组命令提供参数,要执行一些包含标准输入的多个参数的命令,可以使用非常巧妙的方式,称为子shell妙招,一个包含while循环的子shell可以用来读取参数

cat files.txt | (while read arg;do cat $arg; done)

相当于 cat files.txt | xargs -I {} cat {}

这样就可以对一个参数执行多项命令,而起整个子shell可以作为一个整体执行

图片

发表评论

邮箱地址不会被公开。 必填项已用*标注