I would have assumed that following examples work perfectly fine.
$ 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
But they don't work at all when I run it interactively it doesn't even substitute the string. I see no note in manual page regarding a special case in first position. Why does this not work?
$ 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
This is even more surprising because it does substitute correctly.
How can I use the argument in first place? I don't want to use ... -I py sh -c "py --version"
because this will create a new sub-process. I wish to know how to eval command in current env.
Best Answer
In
xargs -I replstr utility arguments
, POSIX requires that thereplstr
be only substituted in thearguments
, notutility
. GNUxargs
is compliant in that regard (busyboxxargs
is not).To work around it, you can use
env
as the utility:(chokes on leading whitespace, backslash, single quote, double quote, newline, possibly sequences of bytes nor forming valid characters, because of the way
xargs
interprets its input).Or better:
Which would limit problematic characters in file names to newline only.
In any case, you can't and don't want to use
eval
here.eval
is the shell builtin (special builtin in POSIX shells) command to interpret shell code, not to run commands.xargs
is an external command to the shell, so it cannot run builtins of your shell or of any shell without starting an interpreter of that shell like with:Using
sh
instead offish
here as AFAIKfish
inline scripts can't take arguments. But still not usingeval
here which wouldn't make sense as we don't want those file names to be interpreted as shell code.Also using
-rd '\n'
which is GNU-specific, but doesn't have all the issues of-I
, to pass the full contents of all lines as separate arguments to the utility (heresh
).