.gzファイルを再帰的にgrepするにはどうすればよいですか?


135

スクリプトを使用して、生の.emlを.gzファイルに圧縮するGmailメッセージを定期的にダウンロードしています。このスクリプトは、毎日フォルダを作成し、すべてのメッセージを独自のファイルに圧縮します。

この文字列で「文字列」を検索する方法が欲しいです。

Grepだけではそれができないようです。SearchMonkeyも試しました。


16
使用zgrepzgrep - search possibly compressed files for a regular expression
Arkadiusz Drabczyk

回答:


141

現在のディレクトリ内のすべての.eml.gzファイルで再帰的にgrepする場合は、次を使用できます。

find . -name \*.eml.gz -print0 | xargs -0 zgrep "STRING"

*シェルが解釈しないように、最初のものをエスケープする必要があります。-print0見つかった各ファイルの後にヌル文字を出力するようにfindに指示します。xargs -0標準入力から読み取り、ファイルごとにコマンドを実行します。zgrepのようgrepに機能しますが、最初にファイルを圧縮解除します。


2
「-print0」および「-0」は必須ではありません。xargsはデフォルトで「\ n」を使用します。
ハイメM.

1
パスにスペース文字が含まれている可能性がある場合に必要です。それらを使用しない複雑さ以外の理由はありません。
ダニエルグリズコム

2
zgrep実際にはgrep、非圧縮ファイルで実行するよりも速いようです。圧縮ファイルはHDから読み取られ、HDから圧縮されていないファイルを読み取るよりも速く解凍できるためです。
ジェレミア

@JaimeM。デフォルトでxargs空白(空白)を使用します。確かに、ファイルに改行が含まれることはほとんどありませんが、スペースは前代未聞ではありません(たとえほとんどのUNIXのタイプがそれらに眉をひそめていても)。とはいえ、空白を心配することなく、より簡単に単純化できます:find . -name '*.eml.gz' -exec zgrep "STRING" {} +起動ごとに同じ多くの引数xargs-print0/ の安全性-0、および余分なプロセスの起動とパイプのオーバーヘッドなしで、かなり簡潔に取得します。-execwith +はPOSIXで指定されているため、私の知る限り、ほとんどの最近のUNIXライクなシステム上にあるはずです。
ShadowRanger 16

@Jaredファイルパターンの先頭のみを知っているワイルドカード検索を行う方法はありますか?たとえば、末尾に日付/時刻のスタンプがある.gzファイルがあります。ABCLog04_18_18_2_21.gz ABC *で始まるファイルを再帰的に検索する方法はありますか。私が交換しようとした\*.eml.gzとの上にあなたの例ではABCLog*:ファイル形式についてのエラーが出るfind: paths must precede expression: ABCLog-2018-03-12-10-16-1.log.gz Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression]
DevelopingDeveloper

68

1つだけではないため、ここには多くの混乱がありzgrepます。システムにはzgrepfrom gzipzgrepfromの2つのバージョンがありzutilsます。前者は、を呼び出す単なるラッパースクリプトですgzip -cdfq-r, --recursiveスイッチはサポートしていません。1
後者はc++プログラムであり、オプションをサポートしてい-r, --recursiveます。
実行zgrep --version | head -n 1すると、そのうちのどれがデフォルトであるかが明らかになります:

zgrep (gzip) 1.6

ラッパースクリプトです。

zgrep (zutils) 1.3

あるcpp実行可能ファイルが。
後者がある場合は、次を実行できます。

zgrep 'pattern' -r --format=gz /path/to/dir

とにかく、提案されているように、find+ zgrepは次のいずれのバージョンでも同様に機能しますzgrep

find /path/to/dir -name '*.gz' -exec zgrep -- 'pattern' {} +

場合はzgrep、あなたのシステムから欠落している(非常に低い)あなたが試みることができます:

find /path/to/dir -name '*.gz' -exec sh -c 'gzip -cd "$0" | grep -- "pattern"' {} \;

ただし、大きな欠点があります。一致する行の前にファイル名が付加されていないため、一致する場所がわかりません。


1:問題があるため


1
zgrepzutilsから入手できない場合は、を使用してUbuntuにインストールできますsudo apt-get install zutils
therealmarv

1
@therealmarvから続き...そして、Ubuntuはgzipの代わりにzutils zgrepを使用します。次に-rが機能します!
イライジャリン

パターンが一致するファイルの行番号を印刷する方法はありますか?
DogEatDog

@DogEatDog-と同様にgrep -nzgrep -n行番号を出力します。マニュアルに記載されています
...-don_crissti

7

agはのバリアントで grep、いくつかの素晴らしい追加機能があります。

  • 圧縮ファイル用の-zオプションがあります。
  • 多くのack機能があります。
  • 速いです

そう:

ag -r -z your-pattern-goes-here   folder

インストールされていない場合、

apt-get install silversearcher-ag   (debian and friends)
yum install the_silver_searcher     (fedora)
brew install the_silver_searcher    (mac)

1
ag: truncated file: Success結果として得られます。他のフラグを追加する必要がありますか?
ヤール

4

再帰だけは簡単です:

   -r, --recursive
          Read all files  under  each  directory,  recursively,  following
          symbolic  links  only  if they are on the command line.  This is
          equivalent to the -d recurse option.

   -R, --dereference-recursive
          Read all files under each directory,  recursively.   Follow  all
          symbolic links, unlike -r.

ただし、圧縮ファイルには次のようなものが必要です。

shopt globstar 
for file in /path/to/directory/**/*gz; do zcat ""$file" | grep pattern; done

path/to/directory 毎日のサブディレクトリを含む親ディレクトリにする必要があります。


zgrepは明らかな答えですが、残念ながら、-rフラグをサポートしていません。からman zgrep

これらのgrepオプションにより、zgrepはエラーコード(-[d rR zZ] | --di * | --exc * | --inc * | --rec * | --nu *)で終了します。


3

システムにzgrepがある場合、簡単にできます

zgrep -irs your-pattern-goes-here the-folder-to-search-goes-here/

システムにzgrepがない場合は、findコマンドを使用して、zcatとgrepを各ファイルに対して次のように実行できます。

find the-folder-to-search-goes-here/ -name '*.gz' \ -exec sh -c 'echo "Searching {}" ; zcat "{}" | grep your-pattern-goes-here ' \;


これを許してください...検索対象のファイルは数層の深さです。〜/ gmvault-db / db / 2015-02には、アーカイブされた各月のフォルダーが含まれ、その下にその月の.gzファイルが保存されます。そのツリー全体で.milを検索する場合、それは私がすることですか?find〜/ gmvault-db / db / -name '* .gz' \ -exec sh -c 'echo "Searching {}"; zcat "{}" | grep .mil '\;
ケンドール

1
-irsの "r"により、zgrepは再帰的に検索されます。findコマンドはデフォルトで再帰的に動作するため、.gzで終わるファイルはすべてzcatされ、grepに渡されます。(および{}は、検索されようとしているファイルの相対パスに展開されます)。したがって、ヒットすると、次のようになります Searching ~/gmvault-db/db/2015-02/03/whatever.gz
ネイトカラマズーから

以下が返されます:find: "式の前にパスが必要です:-exec"ここで使用したコマンドは次のとおりです。find〜/ gmvault-db / db / -name '* .gz' \ -exec sh -c 'echo "Searching { } "; zcat "{}" | grep .mil '\;
ケンドール

「* .gz」と-execの間のバックスラッシュを削除します。
ネイトカラマズー

4
zgrep-r何らかの理由でフラグを取得しません。それについては言及していますman zgrep(私の回答も参照してください)。
テルドン

0

xzgrep -l "string" ./*/*.eml.gz

xzgrepはzgrep utilsの派生物です(/ bin / xzgrep未満)

Manページから:

xzgrepは、非圧縮またはxz(1)、lzma(1)、gzip(1)、bzip2(1)、またはlzop(1)で圧縮されたファイルでgrep(1)を呼び出します。指定されたすべてのオプションは、grep(1)に直接渡されます。

-l一致するファイル名を出力します

-再帰のRは、スクリプトで特に禁止されているため機能しませんが、単純なシェルグロビングはそこに到達するはずです

./*/*.eml.gz

./today/sample.eml.gzの相対パスから、シェル内の相対位置の1レベル下のすべてのインスタンスに一致し、「。eml.gz」で終わる

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