>をxargsコマンドで使用するには?


160

ディレクトリ内のすべてのファイルをgrepして、そのgrepの出力を別のファイルに書き込むbashコマンドを見つけたいと思います。私の推測はこのようなことをすることでした

ls -1 | xargs -I{} "grep ABC '{}' > '{}'.out"

しかし、私の知る限り、xargsは二重引用符が好きではありません。ただし、二重引用符を削除すると、コマンドはコマンド全体の出力を、一連の個々のファイルではなく、「{}」。outという単一のファイルにリダイレクトします。

xargsを使用してこれを行う方法を誰かが知っていますか?このgrepシナリオをxargsの問題を説明する例として使用したので、xargsを使用しない解決策は私には適切ではありません。

回答:


201

これを行うことの間違いをしないでください:

sh -c "grep ABC {} > {}.out"

これは、ファンキーなファイル名を含む多くの条件で壊れ、正しく引用することは不可能です。あなた{}必見常にコードインジェクションのバグを回避するためのコマンドへの単一の完全に別の引数で。あなたがする必要があるのはこれです:

xargs -I{} sh -c 'grep ABC "$1" > "$1.out"' -- {}

xargsだけでなくにも適用されますfind

ちなみに、-0オプションなしでxargsを使用しないでください(データの破壊を心配しない、非常にまれで制御された1回限りのインタラクティブな使用を除きます)。

また、解析しませんls。ずっと。グロビングを使用するか、find代わりに:http://mywiki.wooledge.org/ParsingLs

find再帰を必要とするすべてに使用し、その他すべてのグロブを使用した単純なループ:

find /foo -exec sh -c 'grep "$1" > "$1.out"' -- {} \;

または非再帰的:

for file in *; do grep "$file" > "$file.out"; done

引用符の適切な使用に注意してください。


賛成票を投じたが疑いはある。なしで使用しxargsない-0:これは、でパイプfindの出力をパイプする場合にのみ適用されますよxargsね?私が行うときxargs -a <input_file>、私はこれをどのように使うのでしょうか?grep出力のようなほとんどのコマンド\nとそうではない\0.私がこれを回避するために考えることができる唯一の方法はtr、おそらくそれを修正するために再び使用することです。しかし、それだけで使用することが重要なのはなぜ-0ですか?
legends2k 2014

3
@ legends2kは-0xargsを使用しない場合、ファイル名を取得し、スペース、引用符、バックスラッシュをすべて解除するためです。xargsツールとして忘れてください。行がある場合は、bashループを使用して行を反復します。 while read line; do <command> "$REPLY"; done < file-with-linesまたはcommand | while ...
lhunath

1
うわー、それについては知りませんでした、詳細に感謝します!したがって、移植性のために(すべてxargsがGNUであるわけではないため)、でxargs使用できる場合を除き、回避する必要があります-0。ありがとうございました。
legends2k 2014

1
この特定の使用例の詳細な説明に感謝しますが、問題は、の出力のリダイレクトに関するものでありxargs、必ずしも解析lsや使用を伴うわけではありませんsh -c。これは質問に少しでも答えることはありませんが、質問に対する最初のGoogleの結果であり、混乱を増すだけです。
pandasauce 2017年

1
@Ihunath、こんにちは、あなたの答えは私にとってうまくいきます。しかし、詳細な説明やリンクはありxargs -I{} sh -c 'grep ABC "$1" > "$1.out"' -- {}ますか?特に、埋め込まれた(二重の)引用符の規則と末尾の「-」記号。ありがとう
Scott Yang

40

なしの解決策xargsは次のとおりです:

find . -mindepth 1 -maxdepth 1 -type f -exec sh -c "grep ABC '{}' > '{}.out'" \;

...と同じを行うことができます xargs、それが判明します:

ls -1 | xargs -I {} sh -c "grep ABC '{}' > '{}.out'"

編集lhunathによる発言の後に追加された単一引用符。


彼はxargsを使いたいと言った。私もそれなしで解決策を投稿しましたが、彼がxargsを必要とするのを見つけたら削除しました。
Zifre 2009年

あなたが正しい。私が私の回答を投稿した理由は、何もしないよりも、仕事を終わらせるための代替ソリューションを用意するほうが良いということでした。望ましい答え(つまり、sh -cトリック)を見つけるために、私は正しい方向に進んでいることがわかります。
Stephan202、2009年

14

私はあなたの例が単なる例であり、他のもののために>が必要かもしれないと思います。GNU Parallel http://www.gnu.org/software/parallel/があなたの助けになるかもしれません。ファイル名に\ nが含まれていない限り、追加の引用符は必要ありません。

ls | parallel "grep ABC {} > {}.out"

ファイル名に\ nが含まれている場合:

find . -print0 | parallel -0 "grep ABC {} > {}.out"

追加のボーナスとして、ジョブが並行して実行されます。

詳細については、紹介ビデオをご覧ください:http : //pi.dk/1

10秒のインストールでは、完全インストールが試行されます。それが失敗した場合、個人的なインストール。それが失敗した場合、最小限のインストール:

$ (wget -O - pi.dk/3 || lynx -source pi.dk/3 || curl pi.dk/3/ || \
   fetch -o - http://pi.dk/3 ) > install.sh
$ sha1sum install.sh | grep 3374ec53bacb199b245af2dda86df6c9
12345678 3374ec53 bacb199b 245af2dd a86df6c9
$ md5sum install.sh | grep 029a9ac06e8b5bc6052eac57b2c3c9ca
029a9ac0 6e8b5bc6 052eac57 b2c3c9ca
$ sha512sum install.sh | grep f517006d9897747bed8a4694b1acba1b
40f53af6 9e20dae5 713ba06c f517006d 9897747b ed8a4694 b1acba1b 1464beb4
60055629 3f2356f3 3e9c4e3c 76e3f3af a9db4b32 bd33322b 975696fc e6b23cfb
$ bash install.sh

GNU Parallelがインストールされていないサーバーに移動する必要がある場合は、を試してくださいparallel --embed

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.