xargs
广泛用于shell脚本;通常很容易在 bash using while read -r; do ... done
or while read -ar; do ... done
loops 中重铸这些用途。
什么时候应该xargs
首选,什么时候应该首选 while-read 循环?
循环的问题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
),我将使用while
变体。
在我对性能(大文件)感兴趣的地方,我会使用xargs
,即使我必须编写一个单独的脚本。
的一些实现xargs
还理解一个-P MAX-PROCS
允许xargs
并行运行多个作业的参数。这将很难用while read
循环来模拟。
GNU Parallel http://www.gnu.org/software/parallel/具有xargs
(使用-m)的优点以及while-read
使用换行符作为分隔符和一些新功能的优点(例如输出分组,在远程计算机上并行运行作业和上下文替换)。
如果您安装了 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
“xargs”有选项“-n max-args”,我猜这将允许一次调用多个参数的命令(对“grep”、“rm”和更多这样的程序很有用)尝试手册页中的示例:
cut -d: -f1 < /etc/passwd | sort | xargs -n 5 echo
您会看到它“回显”每行 5 个用户
PS并且不要忘记“xargs” - 是程序(如子shell)。因此,无法以简单的方式将信息获取到您的 shell 脚本(您需要读取“xargs”的输出并以某种方式解释以填充您的 shell/env 变量)。
相反,在某些情况下,您有一个文件列表,每行 1 个,包含空格。例如来自 afind
或 apkgutil
或类似的。要与xargs
您合作,您必须使用 first 将行括在引号中sed
,但这看起来很笨拙。
使用 while 循环,脚本可能看起来更容易读/写。并且引用空间污染的参数是微不足道的。下面的示例是人为的,但想象一下从find
...以外的其他地方获取文件列表
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 脚本来完成。