使用 parallel 和引用文件名列表作为输入调用 shell 函数
calling shell function using parallel with list of quoted filenames as input
使用 Bash.
我有一个导出的 shell 函数,我想将其应用于许多文件。
通常我会使用 xargs,但像这样的语法(参见 here)太难用了。
...... | xargs -n 1 -P 10 -I {} bash -c 'echo_var "$@"' _ {}
在那次讨论中,parallel
有一个更简单的语法:
..... | parallel -P 10 echo_var {}
现在我 运行 遇到了以下问题:我要应用我的函数的文件列表是一行文件列表,每个文件都用 spaces 引用和分隔因此:
"file 1" "file 2" "file 3"
。
如何将这个 space 分隔、引用、列表输入 parallel
?
我可以使用 echo
复制列表进行测试。
例如
echo '"file 1" "file 2" "file 3"'|parallel -d " " my_function {}
但我无法让它工作。
我该如何解决?
How can I fix it?
您必须选择一个唯一的分隔符。
echo 'file 1|file 2|file 3' | xargs -d "|" -n1 bash -c 'my_function "$@"' --
echo 'file 1^file 2^file 3' | parallel -d "^" my_function
最安全的是使用零字节作为分隔符:
echo -e 'file 1\x00file 2\x00file 3' | xargs -0 ' -n1 bash -c 'my_function "$@"' --
printf "%s[=11=]" 'file 1' 'file 2' 'file 3' | parallel -0 my_function
最好的方法是将元素存储在 bash 数组中,并使用零分隔流来处理它们:
files=("file 1" "file 2" "file 3")
printf "%s[=12=]" "${files[@]}" | xargs -0 -n1 bash -c 'my_function "$@"' --
printf "%s[=12=]" "${files[@]}" | parallel -0 my_function
请注意,空数组将 运行 函数不带任何参数。当输入为空时,有时首选使用 -r
--no-run-if-empty
选项而不是 运行 函数。 --no-run-if-empty
受 parallel
支持,并且是 xargs
中的 gnu 扩展(BSD 上的 xargs
和 OSX 上没有 --no-run-if-empty
)。
注意:xargs
默认解析 '
、"
和 \
。这就是为什么以下是可能的并且会起作用的原因:
echo '"file 1" "file 2" "file 3"' | xargs -n1 bash -c 'my_function "$@"' --
echo "'file 1' 'file 2' 'file 3'" | xargs -n1 bash -c 'my_function "$@"' --
echo 'file\ 1 file\ 2 file\ 3' | xargs -n1 bash -c 'my_function "$@"' --
它可能会导致一些奇怪的事情,所以请记住几乎总是为 xargs
指定 -d
选项:
$ # note \x replaced by single x
$ echo '\a\b\c' | xargs
\abc
$ # quotes are parsed and need to match
$ echo 'abc"def' | xargs
xargs: unmatched double quote; by default quotes are special to xargs unless you use the -0 option
$ echo "abc'def" | xargs
xargs: unmatched single quote; by default quotes are special to xargs unless you use the -0 option
xargs
是随处可用的便携工具,而 parallel
是 GNU 程序,必须单独安装。
问题归结为值可以包含space,而space是值分隔符。所以我们需要一些可以将输入解析为包含 space 的单独值的东西。由于它们被 bash 引用,因此显而易见的选择是使用 bash 取消对值的引用。
您有多种选择:
(echo "file 1";
echo "file 2";
echo "file \"name\" $(3)") | parallel my_function
printf "%s\n" "file 1" "file 2" "file \"name\" $(3)" |
parallel my_function
如果输入在变量中:
var='"file 1" "file 2" "file \"name\" $(3)"'
eval 'printf "%s\n" '"$var" |
parallel my_function
或者您可以将变量转换为数组:
var='"file 1" "file 2" "file \"name\" $(3)"'
eval arr=("$var")
如果输入在数组中:
parallel my_function ::: "${arr[@]}"
使用 Bash.
我有一个导出的 shell 函数,我想将其应用于许多文件。
通常我会使用 xargs,但像这样的语法(参见 here)太难用了。
...... | xargs -n 1 -P 10 -I {} bash -c 'echo_var "$@"' _ {}
在那次讨论中,parallel
有一个更简单的语法:
..... | parallel -P 10 echo_var {}
现在我 运行 遇到了以下问题:我要应用我的函数的文件列表是一行文件列表,每个文件都用 spaces 引用和分隔因此:
"file 1" "file 2" "file 3"
。
如何将这个 space 分隔、引用、列表输入 parallel
?
我可以使用 echo
复制列表进行测试。
例如
echo '"file 1" "file 2" "file 3"'|parallel -d " " my_function {}
但我无法让它工作。
我该如何解决?
How can I fix it?
您必须选择一个唯一的分隔符。
echo 'file 1|file 2|file 3' | xargs -d "|" -n1 bash -c 'my_function "$@"' --
echo 'file 1^file 2^file 3' | parallel -d "^" my_function
最安全的是使用零字节作为分隔符:
echo -e 'file 1\x00file 2\x00file 3' | xargs -0 ' -n1 bash -c 'my_function "$@"' --
printf "%s[=11=]" 'file 1' 'file 2' 'file 3' | parallel -0 my_function
最好的方法是将元素存储在 bash 数组中,并使用零分隔流来处理它们:
files=("file 1" "file 2" "file 3")
printf "%s[=12=]" "${files[@]}" | xargs -0 -n1 bash -c 'my_function "$@"' --
printf "%s[=12=]" "${files[@]}" | parallel -0 my_function
请注意,空数组将 运行 函数不带任何参数。当输入为空时,有时首选使用 -r
--no-run-if-empty
选项而不是 运行 函数。 --no-run-if-empty
受 parallel
支持,并且是 xargs
中的 gnu 扩展(BSD 上的 xargs
和 OSX 上没有 --no-run-if-empty
)。
注意:xargs
默认解析 '
、"
和 \
。这就是为什么以下是可能的并且会起作用的原因:
echo '"file 1" "file 2" "file 3"' | xargs -n1 bash -c 'my_function "$@"' --
echo "'file 1' 'file 2' 'file 3'" | xargs -n1 bash -c 'my_function "$@"' --
echo 'file\ 1 file\ 2 file\ 3' | xargs -n1 bash -c 'my_function "$@"' --
它可能会导致一些奇怪的事情,所以请记住几乎总是为 xargs
指定 -d
选项:
$ # note \x replaced by single x
$ echo '\a\b\c' | xargs
\abc
$ # quotes are parsed and need to match
$ echo 'abc"def' | xargs
xargs: unmatched double quote; by default quotes are special to xargs unless you use the -0 option
$ echo "abc'def" | xargs
xargs: unmatched single quote; by default quotes are special to xargs unless you use the -0 option
xargs
是随处可用的便携工具,而 parallel
是 GNU 程序,必须单独安装。
问题归结为值可以包含space,而space是值分隔符。所以我们需要一些可以将输入解析为包含 space 的单独值的东西。由于它们被 bash 引用,因此显而易见的选择是使用 bash 取消对值的引用。
您有多种选择:
(echo "file 1";
echo "file 2";
echo "file \"name\" $(3)") | parallel my_function
printf "%s\n" "file 1" "file 2" "file \"name\" $(3)" |
parallel my_function
如果输入在变量中:
var='"file 1" "file 2" "file \"name\" $(3)"'
eval 'printf "%s\n" '"$var" |
parallel my_function
或者您可以将变量转换为数组:
var='"file 1" "file 2" "file \"name\" $(3)"'
eval arr=("$var")
如果输入在数组中:
parallel my_function ::: "${arr[@]}"