xargs | 使用输入作为命令

use*_*492 5 shell xargs fish

我会假设下面的例子工作得很好。

$ which -a python python3 pip | xargs -I {} {} --version
No '{}' such file or folder
$ which -a python python3 pip | xargs -I _ _ --version
No '_' such file or folder
$ which -a python python3 pip | xargs -I py py --version
No 'py' such file or folder
Run Code Online (Sandbox Code Playgroud)

但是当我以交互方式运行它时,它们根本不起作用,它甚至不替换字符串。我在手册页中没有看到关于第一个位置的特殊情况的注释。为什么这不起作用?

$ which -a python python3 pip | xargs -I py -p eval py --version
eval ~/.pyenv/shims/python --version?...y
xargs: eval: No such file or directory
Run Code Online (Sandbox Code Playgroud)

这更令人惊讶,因为它确实正确替换了。

我如何首先使用参数?我不想使用,... -I py sh -c "py --version"因为这会创建一个新的子流程。我想知道如何在当前环境中评估命令。

Sté*_*las 10

在 中xargs -I replstr utility argumentsPOSIX 要求replstr仅在 中被替换,而arguments不是在 中被替换utility。GNUxargs在这方面是合规的(busyboxxargs不是)。

要解决它,您可以使用env以下实用程序:

which -a ... | xargs -I cmd xargs env cmd --version
Run Code Online (Sandbox Code Playgroud)

(由于xargs解释其输入的方式,在前导空格、反斜杠、单引号、双引号、换行符、可能的字节序列或形成有效字符时窒息)。

或更好:

for cmd in (which -a ...)
  $cmd --version
end
Run Code Online (Sandbox Code Playgroud)

这会将文件名中的问题字符限制为仅换行符。

无论如何,您不能也不想在eval这里使用。eval是 shell 内置(POSIX shell 中的特殊内置)命令来解释 shell 代码,而不是运行命令。xargs是 shell 的外部命令,因此如果不启动该 shell 的解释器,它就无法运行您的 shell 或任何 shell 的内置命令,例如:

which -a ... |
  xargs -rd '\n' sh -c 'for cmd do "$cmd" --version; done' sh
Run Code Online (Sandbox Code Playgroud)

使用sh而不是fishhere 作为 AFAIKfish内联脚本不能接受参数。但是仍然使用eval这里没有意义,因为我们不希望这些文件名被解释为 shell 代码。

还使用-rd '\n'which 是 GNU 特定的,但没有 , 的所有问题-I,将所有行的完整内容作为单独的参数传递给实用程序(此处sh)。