GNUparallel
是xargs
. 它们都有非常相似的界面,如果您正在寻找有关 的帮助parallel
,您可能会更幸运地查找有关 的信息xargs
。
话虽如此,它们的操作方式都相当简单。使用它们的默认行为,两个程序都从 STDIN 读取输入,然后根据空格将输入分解为标记。然后将这些标记中的每一个作为参数传递给提供的程序。xargs 的默认设置是将尽可能多的令牌传递给程序,然后在达到限制时启动一个新进程。我不确定并行的默认设置是如何工作的。
这是一个例子:
> echo "foo bar \
baz" | xargs echo
foo bar baz
默认行为存在一些问题,因此通常会看到几种变化。
第一个问题是,因为空格用于标记化,任何包含空格的文件都会导致并行和 xargs 中断。一种解决方案是改为围绕 NULL 字符进行标记。find
甚至提供了一个选项来使这很容易做到:
> echo "Success!" > bad\ filename
> find . "bad\ filename" -print0 | xargs -0 cat
Success!
该-print0
选项告诉find
使用 NULL 字符而不是空格分隔文件。
该-0
选项告诉xargs
使用 NULL 字符来标记每个参数。
请注意,这parallel
比xargs
它的默认行为是仅围绕换行符进行标记要好一些,因此不需要更改默认行为。
另一个常见问题是您可能想要控制如何将参数传递给xargs
or parallel
。如果您需要将参数传递给程序的特定位置,您可以使用{}
来指定参数的放置位置。
> mkdir new_dir
> find -name *.xml | xargs mv {} new_dir
这会将当前目录和子目录中的所有文件移动到 new_dir 目录中。它实际上分为以下几部分:
> find -name *.xml | xargs echo mv {} new_dir
> mv foo.xml new_dir
> mv bar.xml new_dir
> mv baz.xml new_dir
因此,考虑到如何xargs
和parallel
工作,您应该希望能够看到您的命令的问题。find . -name '*.xml'
将生成要传递给script.sh
程序的 xml 文件列表。
> find . -name '*.xml' | parallel -j2 echo script.sh {}
> script.sh foo.xml
> script.sh bar.xml
> script.sh baz.xml
但是,ls | parallel -j2 script.sh {}
会生成当前目录中所有文件的列表以传递给 script.sh 程序。
> ls | parallel -j2 echo script.sh {}
> script.sh some_directory
> script.sh some_file
> script.sh foo.xml
> ...
该版本的更正确变体ls
如下:
> ls *.xml | parallel -j2 script.sh {}
但是,这与 find 版本之间的重要区别在于 find 将在所有子目录中搜索文件,而 ls 将仅搜索当前目录。find
上述命令的等效版本ls
如下:
> find -maxdepth 1 -name '*.xml'
这只会搜索当前目录。