it-swarm.com.de

Wie grep ich rekursiv durch .gz-Dateien?

Ich verwende ein Skript, um regelmäßig meine Google Mail-Nachrichten herunterzuladen, die die unformatierte EML-Datei in GZ-Dateien komprimieren. Das Skript erstellt für jeden Tag einen Ordner und komprimiert dann jede Nachricht in eine eigene Datei.

Ich möchte in diesem Archiv nach einer "Zeichenfolge" suchen.

Grep allein scheint es nicht zu tun. Ich habe auch SearchMonkey ausprobiert.

144
Kendor

Wenn Sie in allen .eml.gz-Dateien im aktuellen Verzeichnis rekursiv grep möchten, können Sie Folgendes verwenden:

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

Du musst dem ersten entkommen * damit die Shell es nicht interpretiert. -print0 weist find an, nach jeder gefundenen Datei ein Nullzeichen zu drucken. xargs -0 liest aus der Standardeingabe und führt danach den Befehl für jede Datei aus; zgrep funktioniert wie grep, dekomprimiert jedoch zuerst die Datei.

153
J. K. Stafford

Hier herrscht große Verwirrung, weil es nicht nur ein zgrep gibt. Ich habe zwei Versionen auf meinem System, zgrep von gzip und zgrep von zutils . Ersteres ist nur ein Wrapper-Skript, das gzip -cdfq. Es unterstützt nicht das -r, --recursive Schalter.1
Letzteres ist ein c++ Programm und es nterstützt das -r, --recursive Möglichkeit.
Laufen zgrep --version | head -n 1 zeigt an, welche (falls vorhanden) die Standardeinstellung ist:

zgrep (gzip) 1.6

ist das Wrapper-Skript,

zgrep (zutils) 1.3

ist die ausführbare Datei cpp.
Wenn Sie letzteres haben, könnten Sie laufen:

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

Wie vorgeschlagen funktioniert find + zgrep mit beiden Versionen von zgrep gleich gut:

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

Wenn zgrep in Ihrem System fehlt (höchst unwahrscheinlich), können Sie Folgendes versuchen:

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

aber es gibt einen großen Nachteil: Sie werden nicht wissen, wo die Übereinstimmungen sind, da den übereinstimmenden Zeilen kein Dateiname vorangestellt ist.


1: weil es problematisch wäre

70
don_crissti

ag ist eine Variante von grep mit einigen netten Zusatzfunktionen.

  • hat die Option -z für komprimierte Dateien,
  • hat viele ack-Funktionen.
  • es ist schnell

Damit:

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

Wenn nicht installiert,

apt-get install silversearcher-ag   (debian and friends)
yum install the_silver_searcher     (Fedora)
brew install the_silver_searcher    (mac)
9
JJoao

Rekursion allein ist einfach:

   -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.

Für komprimierte Dateien benötigen Sie jedoch Folgendes:

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

path/to/directory sollte das übergeordnete Verzeichnis sein, das die Unterverzeichnisse für jeden Tag enthält.


zgrep ist die offensichtliche Antwort, unterstützt aber leider nicht die -r Flagge. Von man zgrep:

Diese grep-Optionen führen dazu, dass zgrep mit einem Fehlercode beendet wird: (- [d rR zZ] | --di * | --exc * | --inc * | --rec * | - nu *).

5
terdon

Wenn Ihr System zgrep hat, können Sie einfach

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

Wenn Ihr System nicht über zgrep verfügt, können Sie den Befehl find verwenden, um zcat und grep für jede Datei wie folgt auszuführen:

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

3

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

xzgrep ist eine Ableitung der zgrep-Utils (less/bin/xzgrep)

Von der Manpage:

xzgrep ruft grep (1) für Dateien auf, die entweder unkomprimiert oder mit xz (1), lzma (1), gzip (1), bzip2 (1) oder lzop (1) komprimiert sind. Alle angegebenen Optionen werden direkt an grep (1) übergeben.

-l druckt den passenden Dateinamen

-R für die Rekursion funktioniert nicht, da dies im Skript ausdrücklich verboten ist. Ein einfaches Shell-Globbing sollte uns jedoch dorthin bringen

./*/*.eml.gz

von einem relativen Pfad, in dem ./today/sample.eml.gz auf allen Instanzen übereinstimmt, die eine Ebene unter unserer relativen Position in der Shell liegen, die mit ".eml.gz" endet.

0
John