web-dev-qa-db-ja.com

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

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

このアーカイブで「文字列」を検索する方法を教えてください。

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

144
Kendor

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

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

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

153
J. K. Stafford

zgrepが1つだけではないため、ここには多くの混乱があります。私のシステムには、zgrepからのgzipと、_ zgrep からのzutilsの2つのバージョンがあります。前者は、gzip -cdfqを呼び出す単なるラッパースクリプトです。 -r, --recursiveスイッチはサポートされていません。1
後者はc++プログラムであり、それは supports-r, --recursiveオプションです。
zgrep --version | head -n 1を実行すると、そのうちの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: 問題が発生するため

70
don_crissti

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

  • 圧縮ファイル用の-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)
9
JJoao

再帰だけでも簡単です:

   -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 *)。

5
terdon

システムに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 ' \;

3

xzgrep -l "文字列" ./*/*.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」で終わるすべてのインスタンスに一致

0
John