リストからgrepファイル


14

数百のファイルのリストに対してgrepを実行しようとしています。

$ head -n 3 <(cat files.txt)
admin.php
ajax/accept.php
ajax/add_note.php

ただし、ファイル内で見つかったことがわかっている文字列を探していても、次のコマンドはファイルを検索しません。

$ grep -i 'foo' <(cat files.txt)

$ grep -i 'foo' admin.php
The foo was found

ファイルからパターン-fを読み取るフラグに精通しています。しかし、入力ファイルの読み方は?

私は、ファイルを一時ディレクトリにコピーするという恐ろしい回避策を考えていたのでcp<(cat files.txt)フォーマットをサポートしているようで、そこからファイルをgrepします。シャーリーにはもっと良い方法があります。

回答:


22

ファイル自体ではなく、ファイル名のリストを把握しているようです。<(cat files.txt)ファイルをリストするだけです。試してみてください<(cat $(cat files.txt))、実際にそれらを連結し、単一のストリームとしてそれらを検索しますか、

grep -i 'foo' $(cat files.txt)

grepにすべてのファイルを提供します。

ただし、リスト上のファイルが多すぎる場合、引数の数に問題がある可能性があります。その場合、私はただ書きます

while read filename; do grep -Hi 'foo' "$filename"; done < files.txt

ありがとうございました!whilefile.txtの行をそのまま受信できることに気づきませんでした。
-dotancohen

ここで、そのsplit + glob演算子のglob部分を無効にします(シェルがzshでない場合)。
ステファンシャゼル

1
whileファイルから行を正確に受け取っていない、それreadをしている; whileループでそれを行うだけです。ループはread、通常、ファイルの終わりに到達したために、失敗すると終了します(つまり、ゼロ以外の戻りコードを返します)。
PM 2Ring

1
(テキスト)行を読み取るための構文はIFS= read -r filenameread filename別のものです。
ステファンシャゼル

1
これ-HはGNU拡張機能であることに注意してください。あなたはいくつかを逃してい--ます。
ステファンシャゼル

8
xargs grep -i -- foo /dev/null < files.txt

ファイルが空白または改行で区切られていると仮定します(引用符またはバックスラッシュを使用してこれらの区切り文字をエスケープできます)。GNU xargsでは、区切り文字を指定できます-d(ただし、引用符の処理は無効になります)。

(unset -v IFS; set -f; grep -i -- foo $(cat files.txt))

ファイルがスペース、タブ、または改行で区切られていると仮定します(それらをエスケープする方法はありませんが、別の区切り文字をに割り当てることで選択できますIFS)。ほとんどのシステムでファイルリストが大きすぎる場合、これは失敗します。

また、これらのファイルはいずれも呼び出されないと想定しています-


少なくともおよびの$(< file)代わりに$(cat file)、の代わりに使用する方が優れています。bashzsh
-jimmij

7

stdinからファイル名のリストを読み取るには、を使用できますxargs。例えば、

cat files.txt | xargs -d'\n' grep -i -- 'foo'

デフォルトでは、xargs空白で区切られた標準入力からアイテムを読み取ります。-d'\n'それは空白を含むファイル名を処理することができますので、引数の区切り文字として改行を使用するように指示します。(StéphaneChazelasが指摘しているように、それはGNU拡張機能です)。ただし、改行を含むファイル名には対応しません。それらを処理するには、もう少し複雑なアプローチが必要です。

FWIW、while readbashのreadコマンドは非常に遅いため、このアプローチはループよりもやや高速です-データを1文字ずつxargs読み取りますが、入力をより効率的に読み取ります。また、コマンドは必要な回数xargsだけ呼び出すだけgrepで、各呼び出しは複数のファイル名を受け取るgrepため、ファイル名ごとに個別に呼び出すよりも効率的です。

詳細については、xargsのマニュアルページとxargsの情報ページを参照してください。


3

xargsfiles.txtオプションを使用して、ファイル(リストなど)からアイテムを読み取ることができます。

   --arg-file=file
   -a file
          Read items from file instead of standard input.  If you use this
          option, stdin remains unchanged when commands are  run.   Other
          wise, stdin is redirected from /dev/null.

したがって、これも動作するはずです:

xargs -a files.txt grep -i 'foo'

またはファイル名のスペース用

xargs -d'\n' -a files.txt grep -i 'foo'
xargs -I{} -a files.txt grep -i 'foo' {}

1

forを実行することもできますが、Orionの例は最も簡単です。

for i in $(cat files.txt); do grep -i 'foo' $i ; done

(files.txtにリストされている各ファイルに対して、grepコマンドを実行します。)

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