xargs 不适用于内置 shell 函数

xargs not working with built in shell functions

我正在尝试加快数据库的处理速度。我迁移到 xargs。但我被严重困住了。如果 xargs 调用的命令不是内置命令,则将参数列表传送到 xargs 不起作用。我不明白为什么。这是我的代码:

#!/bin/bash

list='foo
bar'

test(){
    echo "" 
}

echo "$list" | tr '2' '[=11=]0' | xargs -0 -n1 -I '{}' 'test' {}

所以根本没有输出。测试功能永远不会被执行。但是,如果我将 "xargs" 命令中的 "test" 替换为 "echo" 或 "printf",它就可以正常工作。

xargs 将可执行文件作为参数(包括自定义脚本)而不是环境中定义的函数。

将您的代码移动到脚本或使用 xargs 将参数传递给外部命令。

您不能将 shell 函数直接传递给 xargs,但您可以调用 shell.

printf 'foo[=10=]bar[=10=]' |
xargs -r -0 sh -c 'for f; do echo "$f"; done' _

sh -c '...'里面的东西可以任意复杂;如果你真的想要,你可以声明然后使用你的函数。但由于它简单且非递归,我只是内联了功能。

虚拟下划线参数是因为sh -c 'script'之后的第一个参数用于填充[=14=]

因为你的问题似乎是关于优化的,我想你不想为传递给 xargs 的每个项目生成一个单独的 shell - 如果你这样做,没有什么会变得更快.所以我放入 for 循环并取出 -I 等参数 xargs.

更改自:

echo "$list" | tr '2' '[=10=]0' | xargs -0 -n1 -I '{}' 'test' {}

收件人:

export -f test
echo "$list" | tr '2' '[=11=]0' | xargs -0 -n1 -I '{}' sh -c 'test {}'

我在 bbs.archlinux.org 网站上看到 'jac' 的解决方案,该解决方案使用一对非常高效的主要和次要(从属)脚本。与通常接受单个 $1 参数的内部 'function' 不同,主节点向其次节点发送参数列表,其中 while 循环将列表的每个成员作为连续的 $1 值处理。这是我用来将 'file' 命令应用于一堆可执行文件的示例对,在我的例子中,这些可执行文件的文件名都以 "em" 开头。根据需要进行更改:

#!/bin/bash
# primary:  showfil
ls -l em* | grep  '^-rwx' | awk '{========""; print [=10=]}' | xargs -I% ~/showfilf "%"
~/showfilf fixmstr spisort trc
exit 0

#!/bin/bash
# secondary:  showfilf
myarch=$(uname -s | grep 'arwin')
while [[ -n "" ]]; do
  if [ -x "" ]; then
     if [ -n "$myarch" ]; then
        file "./"
     else
        myfile=$(file "./" | awk '{print " "" "" "" "}')
        myfile=${myfile%(uses}
        myfile=${myfile%for}
        echo "$myfile"
     fi
  fi
  shift
done
exit 0

此代码适用于 Darwin (Mac) 和 Linux,可能还有其他系统。 primary 中的 'grep' 仅保留可执行文件,不保留目录或符号链接。 'awk' 删除了 'ls' 的前八个字段并仅保留传递给 'xargs' 的文件名,它构建了一个引用文件名列表以发送给 'showfilf'。 'showfilf' 与列表中的其他三个文件名单独调用。 'showfilf' 有一个处理列表的 while 循环。请注意,这里有系统相关的代码,由 'uname -s' 和 'grep' 决定。最后,使这些脚本可执行,并将它们放在您的 $PATH 中,例如 $HOME。如果您的 $PATH 不包含您的 $HOME,我建议您在 .bashrc 或 .bash_login 中修改它,如下所示: export PATH=$PATH:$HOME