以下の例が正しく機能すると思いました。
$ 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
しかし、インタラクティブに実行するとまったく機能せず、文字列も置き換えません。最初の場所に関する特別なケースの説明は、マニュアルページには表示されません。なぜこれがうまくいかないのですか?
$ 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
これは正しく置き換えられるので、さらに驚くべきことです。
最初にこの主張をどのように使用できますか?... -I py sh -c "py --version"
新しいサブプロセスが作成されるため、使用したくありません。現在の環境でコマンドを評価する方法を知りたいです。
答え1
存在するxargs -I replstr utility arguments
、POSIXの要件replstr
でのみ交換でき、 では交換できarguments
ませんutility
。 GNUはxargs
これに関して互換性があります(busyboxは互換性がxargs
ありません)。
env
この問題を解決するには、次のユーティリティを使用できます。
which -a ... | xargs -I cmd xargs env cmd --version
(xargs
先行スペース、バックスラッシュ、一重引用符、二重引用符、改行、可能なバイトシーケンス、または入力が解釈される方法によって有効な文字を形成するためのブロック)。
またはより良い:
for cmd in (which -a ...)
$cmd --version
end
これにより、ファイル名に問題がある文字は改行文字のみに制限されます。
とにかく、ここでは使用することも、eval
使用したくありません。eval
コマンドを実行する代わりにシェルコードを解釈するために使用されるシェル組み込みコマンド(POSIXシェルの特別な組み込みコマンド)。xargs
はシェルの外部コマンドなので、次のようにシェルのインタプリタを起動しないと、シェルまたはシェルの組み込みコマンドを実行できません。
which -a ... |
xargs -rd '\n' sh -c 'for cmd do "$cmd" --version; done' sh
私が知っている限り、インラインスクリプトはパラメータを受け入れることができないので、ここでsh
代わりに使用してください。しかし、まだfish
fish
いいえeval
これらのファイル名がシェルコードとして解釈されることを望まないので、ここで使用することは意味がありません。
また、-rd '\n'
GNU関連ではあるが存在しない問題を使用して、-I
すべての行の内容全体をユーティリティ(ここsh
)に別々の引数として渡します。