xargs
被广泛用于shell脚本中; while read -r; do ... done
通常很容易在bash中重新使用这些用法while read -r; do ... done
while read -r; do ... done
或while 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” – 是程序(如subshell)。 因此,没有办法以简单的方式获取信息到你的shell脚本(你需要读取你的“xargs”的输出,并以某种方式解释填充你的shell / env变量)。
xargs
一些实现也理解一个-P MAX-PROCS
参数,它允许xargs
并行运行多个作业。 这将是很难用一个while read
循环来模拟。
GNU并行http://www.gnu.org/software/parallel/从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个,包含空格。 例如来自一个find
或pkgutil
或类似的。 要使用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脚本来完成。