182

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

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

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

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

4

4 に答える 4

222

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

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

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

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

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

于 2009-05-10T19:22:38.640 に答える
45

なしの解決策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によるコメントの後に追加された一重引用符。

于 2009-05-10T18:59:23.687 に答える
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 883c667e01eed62f975ad28b6d50e22a
12345678 883c667e 01eed62f 975ad28b 6d50e22a
$ md5sum install.sh | grep cc21b4c943fd03e93ae1ae49e28573c0
cc21b4c9 43fd03e9 3ae1ae49 e28573c0
$ sha512sum install.sh | grep da012ec113b49a54e705f86d51e784ebced224fdf
79945d9d 250b42a4 2067bb00 99da012e c113b49a 54e705f8 6d51e784 ebced224
fdff3f52 ca588d64 e75f6033 61bd543f d631f592 2f87ceb2 ab034149 6df84a35
$ bash install.sh

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

于 2010-06-10T18:27:28.607 に答える