xargs
广泛用于shell脚本;使用while read -r; do ... done
或while read -ar; do ... done
循环通常很容易在bash中重新构建这些用法。
何时应首选xargs
,何时首选while-read循环?
答案 0 :(得分:25)
具有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
在这里,您可以看到这些行与while
一起逐个处理,并与xargs
一起处理。换句话说,前者等同于echo 1 ; echo 2 ; echo 3 ; echo 4 ; echo 5
,而后者等同于echo 1 2 3 4 5
(五个过程而不是一个过程)。这在处理数千或数万行时确实有所不同,因为创建流程需要时间。
使用可以接受多个参数的命令最有利,因为它减少了启动的单个进程的数量,使事情变得更快。
当我处理小文件或者在每个项目上运行的命令都很复杂时(我懒得写一个单独的脚本来提供给xargs
),我将使用{{1}变种。
我对性能(大文件)感兴趣,即使我必须编写单独的脚本,我也会使用while
。
答案 1 :(得分:5)
“xargs”有选项“-n max-args”,我想这将允许一次调用几个参数的命令(对“grep”,“rm”以及更多此类程序有用) 试试man-page的例子:
cut -d: -f1 < /etc/passwd | sort | xargs -n 5 echo
你会看到它“回应” - 每行5个用户
P.S。并且不要忘记“xargs” - 是程序(如子shell)。因此无法以简单的方式获取shell脚本的信息(您需要读取“xargs”的输出并以某种方式解释以填充shell / env变量)。
答案 2 :(得分:5)
xargs
的某些实现也理解-P MAX-PROCS
参数,它允许xargs
并行运行多个作业。使用while read
循环进行模拟非常困难。
答案 3 :(得分:5)
GNU Parallel http://www.gnu.org/software/parallel/具有xargs
(使用-m)和while-read
的优点,其中newline作为分隔符和一些新功能(例如输出分组,并行运行远程计算机上的作业和上下文替换。)
如果您安装了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
答案 4 :(得分:2)
相反,有些情况下你有一个文件列表,每行1个,包含空格。例如。来自find
或pkgutil
或类似的。要使用xargs
,您必须首先使用sed
用引号括起来,但这看起来很笨拙。
使用while循环,脚本可能看起来更容易读/写。引用受空间污染的args是微不足道的。下面的示例是人为的,但想象一下从find
...
function process {
while read line; do
test -d "$line" && echo "$line"
done
}
find . -name "*foo*" | process
答案 5 :(得分:1)
我不明白,人们一直在讨论如何在循环中而不是在循环之外执行。我对linux的方面知之甚少,但我知道使用MS-DOS的变量构建参数列表相当简单,或者&gt; file,cmd&lt;如果超出行长度限制,则建立参数列表。
或者有人说linux不像ms-dos那么好吗? (天啊,我知道你可以构建链,因为许多bash脚本显然正在这样做,而不是在循环中)。
此时,它成为内核限制/偏好的问题。 xargs并不神奇;管道确实比字符串构建有好处(好吧,ms-dos;你可以用#34;指针和#34构建字符串;并且避免任何复制(毕竟它是虚拟内存,除非你要更改数据)你可以跳过字符串concat中的费用...但管道是一个更原生的支持))。实际上,我不认为我可以给它带来并行处理的优势,因为你可以轻松地创建几个任务循环来查看切片数据(如果你避免复制,这也是一个非常快速的动作)。
最后,xargs更多用于内联命令,速度优势可以忽略不计(编译/解释字符串构建之间的差异)因为它所做的一切,你可以通过shell脚本来完成。