我试图使用xargs并行调用一个更复杂的函数。
#!/bin/bash
echo_var(){
echo $1
return 0
}
seq -f "n%04g" 1 100 |xargs -n 1 -P 10 -i echo_var {}
exit 0
这将返回错误
xargs: echo_var: No such file or directory
任何关于如何使用xargs或任何其他解决方案的想法都是受欢迎的。
我试图使用xargs并行调用一个更复杂的函数。
#!/bin/bash
echo_var(){
echo $1
return 0
}
seq -f "n%04g" 1 100 |xargs -n 1 -P 10 -i echo_var {}
exit 0
这将返回错误
xargs: echo_var: No such file or directory
任何关于如何使用xargs或任何其他解决方案的想法都是受欢迎的。
当前回答
导出函数应该这样做(未经测试):
export -f echo_var
seq -f "n%04g" 1 100 | xargs -n 1 -P 10 -I {} bash -c 'echo_var "$@"' _ {}
你可以使用内置printf代替外部seq:
printf "n%04g\n" {1..100} | xargs -n 1 -P 10 -I {} bash -c 'echo_var "$@"' _ {}
同样,像这样使用return 0和exit 0可以掩盖前面的命令可能产生的任何错误值。此外,如果没有错误,则它是默认值,因此有点多余。
@ phobia提到Bash命令可以简化为
bash -c 'echo_var "{}"'
将{}直接移动到其中。但是正如@Sasha指出的,它很容易受到命令注入的攻击。
下面是一个你不应该使用嵌入式格式的例子:
$ echo '$(date)' | xargs -I {} bash -c 'echo_var "{}"'
Sun Aug 18 11:56:45 CDT 2019
另一个例子:
echo '\"; date\"' | xargs -I {} bash -c 'echo_var "{}"'
这是使用安全格式输出的内容:
$ echo '$(date)' | xargs -I {} bash -c 'echo_var "$@"' _ {}
$(date)
这类似于使用参数化SQL查询来避免注入。
我在命令替换或转义引号中使用date,而不是Sasha注释中使用的rm命令,因为它是非破坏性的。
其他回答
像这样的东西也应该工作:
function testing() { sleep $1 ; }
echo {1..10} | xargs -n 1 | xargs -I@ -P4 bash -c "$(declare -f testing) ; testing @ ; echo @ "
看来我不能发表评论了:-(
我想知道你对
bash -c 'echo_var "$@"' _ {}
vs
bash -c 'echo_var "{}"'
第一个替换{}作为bash的参数,而第二个替换为函数的参数。示例1没有展开$(date)这一事实只是一个副作用。
如果你不想扩展函数的参数,使用单引号而不是双引号。为了避免混乱的嵌套,使用双引号(在另一个上展开参数)
$ echo '$(date)' | xargs -0 -L1 -I {} bash -c 'printit "{}"'
Fri 11 Sep 17:02:24 BST 2020
$ echo '$(date)' | xargs -0 -L1 -I {} bash -c "printit '{}'"
$(date)
使用GNU Parallel是这样的:
#!/bin/bash
echo_var(){
echo $1
return 0
}
export -f echo_var
seq -f "n%04g" 1 100 | parallel -P 10 echo_var {}
exit 0
如果你使用版本20170822,你甚至不需要导出-f,只要你运行这个:
. `which env_parallel.bash`
seq -f "n%04g" 1 100 | env_parallel -P 10 echo_var {}
也许这是不好的做法,但如果你在.bashrc或其他脚本中定义函数,你可以用allexport设置包装文件或至少是函数定义:
set -o allexport
function funcy_town {
echo 'this is a function'
}
function func_rock {
echo 'this is a function, but different'
}
function cyber_func {
echo 'this function does important things'
}
function the_man_from_funcle {
echo 'not gonna lie'
}
function funcle_wiggly {
echo 'at this point I\'m doing it for the funny names'
}
function extreme_function {
echo 'goodbye'
}
set +o allexport
导出函数应该这样做(未经测试):
export -f echo_var
seq -f "n%04g" 1 100 | xargs -n 1 -P 10 -I {} bash -c 'echo_var "$@"' _ {}
你可以使用内置printf代替外部seq:
printf "n%04g\n" {1..100} | xargs -n 1 -P 10 -I {} bash -c 'echo_var "$@"' _ {}
同样,像这样使用return 0和exit 0可以掩盖前面的命令可能产生的任何错误值。此外,如果没有错误,则它是默认值,因此有点多余。
@ phobia提到Bash命令可以简化为
bash -c 'echo_var "{}"'
将{}直接移动到其中。但是正如@Sasha指出的,它很容易受到命令注入的攻击。
下面是一个你不应该使用嵌入式格式的例子:
$ echo '$(date)' | xargs -I {} bash -c 'echo_var "{}"'
Sun Aug 18 11:56:45 CDT 2019
另一个例子:
echo '\"; date\"' | xargs -I {} bash -c 'echo_var "{}"'
这是使用安全格式输出的内容:
$ echo '$(date)' | xargs -I {} bash -c 'echo_var "$@"' _ {}
$(date)
这类似于使用参数化SQL查询来避免注入。
我在命令替换或转义引号中使用date,而不是Sasha注释中使用的rm命令,因为它是非破坏性的。