Dav*_*ave 11 linux parallel-processing bash find gnu-parallel
我正在尝试将GNU parallel大量文件发布到Web服务器.在我的目录中,我有一些文件:
file1.xml
file2.xml
Run Code Online (Sandbox Code Playgroud)
我有一个看起来像这样的shell脚本:
#! /usr/bin/env bash
CMD="curl -X POST -d@$1 http://server/path"
eval $CMD
Run Code Online (Sandbox Code Playgroud)
脚本中还有其他一些东西,但这是最简单的例子.我试图执行以下命令:
ls | parallel -j2 script.sh {}
Run Code Online (Sandbox Code Playgroud)
这些GNU parallel页面显示为对目录中的文件进行操作的"正常"方式.这似乎将文件的名称传递给我的脚本,但curl抱怨它无法加载传入的数据文件.但是,如果我这样做:
find . -name '*.xml' | parallel -j2 script.sh {}
Run Code Online (Sandbox Code Playgroud)
它工作正常.在我的脚本中传递参数的方式ls和find方法之间是否存在差异?或者我是否需要在该脚本中执行其他操作?
GNU parallel是一种变体xargs.它们都有非常相似的界面,如果你正在寻求帮助parallel,你可能会有更多的运气查找有关的信息xargs.
话虽如此,他们的运作方式相当简单.使用默认行为,两个程序都从STDIN读取输入,然后根据空格将输入分解为标记.然后将这些令牌中的每一个作为参数传递给提供的程序.xargs的默认值是将尽可能多的令牌传递给程序,然后在达到限制时启动新进程.我不确定并行的默认值是如何工作的.
这是一个例子:
> echo "foo bar \
baz" | xargs echo
foo bar baz
Run Code Online (Sandbox Code Playgroud)
默认行为存在一些问题,因此通常会看到几种变体.
第一个问题是因为空格用于标记化,所以其中包含空格的任何文件都会导致并行和xargs中断.一种解决方案是改为使用NULL字符进行标记.find甚至提供了一个选项,使这很容易做到:
> echo "Success!" > bad\ filename
> find . "bad\ filename" -print0 | xargs -0 cat
Success!
Run Code Online (Sandbox Code Playgroud)
该-print0选项告诉find使用NULL字符而不是空格分隔文件.
该-0选项告诉xargs使用NULL字符来标记每个参数.
请注意,这parallel比xargs它的默认行为仅仅是新行的标记化要好一些,因此不需要更改默认行为.
另一个常见问题是您可能想要控制参数的传递方式xargs或parallel.如果需要传递给程序的参数的特定位置,可以使用它{}来指定参数的放置位置.
> mkdir new_dir
> find -name *.xml | xargs mv {} new_dir
Run Code Online (Sandbox Code Playgroud)
这会将当前目录和子目录中的所有文件移动到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
Run Code Online (Sandbox Code Playgroud)
因此,考虑到工作方式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
Run Code Online (Sandbox Code Playgroud)
但是,ls | parallel -j2 script.sh {}将生成当前目录中要传递给script.sh程序的ALL文件列表.
> ls | parallel -j2 echo script.sh {}
> script.sh some_directory
> script.sh some_file
> script.sh foo.xml
> ...
Run Code Online (Sandbox Code Playgroud)
该ls版本的更正确的变体如下:
> ls *.xml | parallel -j2 script.sh {}
Run Code Online (Sandbox Code Playgroud)
但是,这和find版本之间的重要区别在于find将在所有子目录中搜索文件,而ls只搜索当前目录.find上述ls命令的等效版本如下:
> find -maxdepth 1 -name '*.xml'
Run Code Online (Sandbox Code Playgroud)
这只会搜索当前目录.
我没有使用过,但¶llel之间有不同。将列出所有文件和目录,其中 as将仅列出以.xml结尾的文件(和目录)。
正如 Paul Rubel 所建议的,只需在脚本中打印 $1 的值即可进行检查。此外,您可能需要考虑仅使用该选项过滤文件的输入。
希望这可以帮助!lsfind . -name '*.xml'lsfind . -name '*.xml'find-type f
| 归档时间: |
|
| 查看次数: |
10763 次 |
| 最近记录: |