web-dev-qa-db-ja.com

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

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

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

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

Xargsを使用してこれを行う方法を知っている人はいますか?このgrepシナリオを例として使用してxargsの問題を説明しているため、xargsを使用しないソリューションは私には当てはまりません。

147
Jesse Shieh

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

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を使用し、その他すべての場合はglobを使用した単純なループを使用します。

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

または非再帰的:

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

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

181
lhunath

xargsを使用しないソリューションは次のとおりです。

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

...そして同じことができますwithxargs、それは判明:

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

Editlhunath によるコメントの後に単一引用符が追加されました。

39
Stephan202

あなたの例は単なる例であり、他のことのために必要になるかもしれないと思います。 GNU Parallel http://www.gnu.org/software/parallel/ があなたの助けになるかもしれません。\nを含む:

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

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

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

追加のボーナスとして、ジョブを並行して実行できます。

編集。

GNU Parallelを次の方法でインストールできます。

wget http://git.savannah.gnu.org/cgit/parallel.git/plain/src/parallel
chmod 755 parallel

詳細については、イントロビデオをご覧ください。 http://pi.dk/1

10秒のインストール:

wget pi.dk/3 -qO - | sh -x
14
Ole Tange