什么时候xargs应该比while-read循环更受欢迎?

xargs被广泛用于shell脚本中; while read -r; do ... done通常很容易在bash中重新使用这些用法while read -r; do ... done while read -r; do ... donewhile read -ar; do ... done while read -ar; do ... done循环。

什么时候应该selectxargs ,什么时候应该读while循环?

while循环的事情是,他们倾向于一次处理一个项目,通常在没有必要的时候处理。 这是xargs一个优势 – 它可以批量调整参数以允许一个命令处理大量项目。

例如,一个while循环:

 pax> echo '1 2 3 4 5' | while read -r; do echo $REPLY; done 1 2 3 4 5 

和相应的xargs

 pax> echo '1 2 3 4 5' | xargs echo 1 2 3 4 5 

在这里你可以看到,这些线条是一个接一个地用xargs 。 换句话说,前者相当于echo 1 ; echo 2 ; echo 3 ; echo 4 ; echo 5 echo 1 ; echo 2 ; echo 3 ; echo 4 ; echo 5 echo 1 ; echo 2 ; echo 3 ; echo 4 ; echo 5而后者相当于echo 1 2 3 4 5 (五个过程而不是一个)。 这在处理数千或数万行时确实有所帮助,因为创建流程需要时间。

当使用可以接受多个参数的命令时,这是非常有利的,因为它减少了启动的单个进程的数量,使事情变得更快。

当我正在处理小文件或命令运行在每个项目是复杂的(我懒得写一个单独的脚本给xargs ),我会使用while变量。

如果我对性能感兴趣(大文件),我会使用xargs ,即使我必须编写单独的脚本。

“xargs”有选项“-n max-args”,我想这将允许一次调用几个参数的命令(对于“grep”,“rm”和更多这样的程序有用)尝试从man-

 cut -d: -f1 < /etc/passwd | sort | xargs -n 5 echo 

你会看到它“回声” – 每行5个用户

PS不要忘记,“xargs” – 是程序(如subshel​​l)。 因此,没有办法以简单的方式获取信息到你的shell脚本(你需要读取你的“xargs”的输出,并以某种方式解释填充你的shell / env变量)。

xargs一些实现也理解一个-P MAX-PROCS参数,它允许xargs并行运行多个作业。 这将是很难用一个while read循环来模拟。

GNU并行http://www.gnu.org/software/parallel/&#x4ECE;xargs (使用-m)和使用换行符作为分隔符的一些新特性(如输出分组,并行运行远程计算机上的作业和上下文替换)。

如果你已经安装了GNU Parallel,我看不到你会使用xargs 。 而我将使用read-while的唯一情况是,如果要执行的块非常大,则放入单个行(例如,如果它包含if语句或类似内容)变得不可读取,并且您拒绝创建bash函数。

对于所有的小脚本,我发现它使用GNU Parallel更具可读性。 paxdiablo的例子:

 echo '1 2 3 4 5' | parallel -m echo 

使用GNU Parallel将WAV文件转换为MP3:

 find sounddir -type f -name '*.wav' | parallel -j+0 lame {} -o {.}.mp3 

观看GNU Parallel的介绍视频: http : //www.youtube.com/watch?v = OpaiGYxkSuQ

相反,有些情况下,你有一个文件列表,每行1个,包含空格。 例如来自一个findpkgutil或类似的。 要使用xargs你必须首先使用sed来包装引号,但这看起来很笨拙。

使用while循环,脚本可能看起来更容易读/写。 引用空间污染的索引是微不足道的。 下面的例子是人为的,但想象得到的东西以外的其他文件列表…

 function process { while read line; do test -d "$line" && echo "$line" done } find . -name "*foo*" | process 

我不明白,人们一直在讨论如何在循环中执行,而不是在循环之外执行。 我知道Linux的一方很少,但是我知道使用MS-DOS的变量来建立一个参数列表是非常简单的,或者如果你超过了行长度限制,使用> file,cmd <file来建立一个参数列表。

还是有人说linux不如ms-dos? (地狱,我知道你可以建立链,因为许多bash脚本显然是这样做的,只是不在循环中)。

在这一点上,它成为内核限制/偏好的问题。 xargs不是神奇的; 管道确实比字符串建立有优势(嗯,MS-DOS;你可以从“指针”中建立字符串,并避免任何复制(毕竟是虚拟内存,除非你改变数据,你可以跳过字符串concat。但管道是一个更原生的支持))。 实际上,我不认为我可以给它并行处理的优势,因为你可以很容易地创建几个任务循环来检查切片数据(如果避免复制,这是一个非常快的操作)。

最后,xargs更多的是内联命令,速度优势是可以忽略的(编译/解释的字符串构建之间的区别),因为它所做的一切,你可以通过shell脚本来完成。