使用xargs调用shell函数

fac*_*ac3 146 bash xargs sh

我试图使用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
Run Code Online (Sandbox Code Playgroud)

这将返回错误

xargs: echo_var: No such file or directory
Run Code Online (Sandbox Code Playgroud)

关于如何使用xargs来完成此任务或任何其他解决方案的任何想法都将受到欢迎.

Pau*_*ce. 151

导出该函数应该这样做(未经测试):

export -f echo_var
seq -f "n%04g" 1 100 | xargs -n 1 -P 10 -I {} bash -c 'echo_var "$@"' _ {}
Run Code Online (Sandbox Code Playgroud)

您可以使用内置printf而不是外部seq:

printf "n%04g\n" {1..100} | xargs -n 1 -P 10 -I {} bash -c 'echo_var "$@"' _ {}
Run Code Online (Sandbox Code Playgroud)

此外,使用return 0exit 0类似掩码可能由其前面的命令产生的任何错误值.此外,如果没有错误,这是默认值,因此有点多余.

  • 多一点讨论:xargs执行一个名为的进程的全新实例.在这种情况下,您提供名称`echo_var`,这是此脚本中的函数,而不是PATH中的进程(程序).Dennis的解决方案所做的是导出子bash进程使用的函数,然后分叉到子进程并在那里执行. (14认同)
  • 您可以通过在命令字符串中将xargs中的参数包含在bash中,并使用`bash -c'echo_var"{}"'`来简化此操作.所以你最后不需要_ {}. (11认同)
  • @Hashbrown:下划线(`_`)为`argv [0]`(`$ 0`)提供了一个占位符,几乎任何东西都可以在那里使用.我想我添加了反斜杠 - 分号('\;`),因为它用于终止`find`中的`-exec`子句,但它在没有它的情况下适用于我.实际上,如果函数使用`$ @`而不是`$ 1`那么它会将分号视为参数,因此应该省略它. (8认同)
  • `_`和````的意义是什么,没有它们它对我不起作用 (6认同)
  • xargs的-i参数已被弃用.请改用-I(大写字母i). (3认同)
  • 添加@Nicolai 提到的`-i` vs. `-I` 问题:[POSIX 甚至没有提到](https://man.openbsd.org/POSIX-2013/xargs) `-i`,提供一个比“只是”弃用更有力的理由。 (2认同)
  • @ phobic,`bash -c'echo_var“ {}”'`是个坏主意。如果输入行包含“”,则不会正确转义。rm -rf“ /`字符串到`xargs -I {} bash -c'echo_var” {}“'`将导致`bash -c'echo_var” hello“; rm -rf” /“'。 (2认同)

Ole*_*nge 16

使用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
Run Code Online (Sandbox Code Playgroud)

如果你使用的是版本20170822,export -f那么只要你运行它就不需要:

. `which env_parallel.bash`
seq -f "n%04g" 1 100 | env_parallel -P 10 echo_var {} 
Run Code Online (Sandbox Code Playgroud)


小智 8

这样的东西也应该起作用:

function testing() { sleep $1 ; }
echo {1..10} | xargs -n 1 | xargs -I@ -P4 bash -c "$(declare -f testing) ; testing @ ; echo @ "
Run Code Online (Sandbox Code Playgroud)