J'utilise un script pour télécharger régulièrement mes messages Gmail qui compresse le fichier .eml brut en fichiers .gz. Le script crée un dossier pour chaque jour, puis compresse chaque message dans son propre fichier.
Je voudrais un moyen de rechercher dans cette archive une "chaîne".
Grep seul ne semble pas le faire. J'ai aussi essayé SearchMonkey.
zgrep
:zgrep - search possibly compressed files for a regular expression
Réponses:
Si vous voulez grep récursivement dans tous les fichiers .eml.gz du répertoire en cours, vous pouvez utiliser:
Vous devez échapper au premier
*
afin que le shell ne l'interprète pas.-print0
indique à find d'imprimer un caractère nul après chaque fichier trouvé;xargs -0
lit à partir de l'entrée standard et exécute la commande après pour chaque fichier;zgrep
fonctionne commegrep
, mais décompresse d'abord le fichier.la source
zgrep
semble en fait plus rapide que degrep
fonctionner sur des fichiers non compressés. Cela doit être dû au fait que les fichiers compressés peuvent être lus sur le disque dur et décompressés plus rapidement que la lecture d’un fichier non compressé à partir du disque dur.xargs
utilise des blancs (espaces) par défaut. Bien sûr, les fichiers ne contiennent presque jamais de nouvelles lignes, mais les espaces ne sont pas inconnus (même si la plupart des types UNIXy les désapprouvent). Cela dit, vous pouvez simplifier encore plus les choses sans vous soucier des espaces: vous obtenezfind . -name '*.eml.gz' -exec zgrep "STRING" {} +
le même nombre d'arguments lors du lancementxargs
, la sécurité de-print0
/-0
et le tout sans les frais généraux liés au lancement d'un processus supplémentaire et à la création d'une tuyauterie, et de manière assez concise.-exec
avec+
est spécifié Posix, il devrait donc être sur la plupart des semi-récents systèmes de type UNIX à ma connaissance.ABCLog04_18_18_2_21.gz
Existe-t-il un moyen de rechercher récursivement des fichiers commençant par ABC *. J'ai essayé de remplacer\*.eml.gz
dans votre exemple ci-dessus avecABCLog*
et obtenir une erreur sur le format de fichier .: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]
Il y a beaucoup de confusion ici car il n'y en a pas qu'un
zgrep
. J'ai deux versions sur mon système,zgrep
degzip
etzgrep
dezutils
. Le premier est juste un script wrapper qui appellegzip -cdfq
. Il ne supporte pas le-r, --recursive
commutateur. 1Ce dernier est un
c++
programme et il prend en charge l'-r, --recursive
option.Running
zgrep --version | head -n 1
indiquera lequel (le cas échéant) est la valeur par défaut:est le script wrapper,
est l'
cpp
exécutable.Si vous avez ce dernier, vous pouvez exécuter:
Quoi qu'il en soit, comme suggéré,
find
+zgrep
fonctionnera également bien avec l'une ou l'autre version dezgrep
:Si
zgrep
est absent de votre système (hautement improbable), vous pouvez essayer avec:mais il y a un inconvénient majeur: vous ne saurez pas où se trouvent les correspondances car aucun nom de fichier n'est ajouté aux lignes correspondantes.
1: parce que ce serait problématique
la source
zgrep
de zutils n'est pas disponible, vous pouvez l'installer dans Ubuntu avecsudo apt-get install zutils
.grep -n
,zgrep -n
affichera le numéro de ligne. C'est dans le manuel ...ag
est une variante degrep
, avec quelques fonctionnalités supplémentaires intéressantes.Alors:
Si non installé,
la source
ag: truncated file: Success
un résultat. Tout autre drapeau dois-je ajouter?La récursion seule est facile:
Cependant, pour les fichiers compressés, vous avez besoin de quelque chose comme:
path/to/directory
devrait être le répertoire parent contenant les sous-répertoires de chaque jour.zgrep
est la réponse évidente, mais, malheureusement, il ne supporte pas le-r
drapeau. Deman zgrep
:la source
Si votre système a zgrep, vous pouvez simplement
zgrep -irs your-pattern-goes-here the-folder-to-search-goes-here/
Si votre système ne dispose pas de zgrep, vous pouvez utiliser la commande find pour exécuter zcat et grep sur chaque fichier de la manière suivante:
find the-folder-to-search-goes-here/ -name '*.gz' \ -exec sh -c 'echo "Searching {}" ; zcat "{}" | grep your-pattern-goes-here ' \;
la source
Searching ~/gmvault-db/db/2015-02/03/whatever.gz
zgrep
ne prendra pas le-r
drapeau pour une raison quelconque. C'est mentionné dansman zgrep
(voir aussi ma réponse).xzgrep est un dérivé des utils zgrep (less / bin / xzgrep)
Depuis la page de manuel:
-l affiche le nom du fichier correspondant
-R pour la récursion ne fonctionnera pas car il est spécifiquement interdit dans le script, mais une simple manipulation de shell devrait nous y amener
à partir d'un chemin relatif où ./today/sample.eml.gz, une correspondance sur toutes les instances correspondant à un niveau inférieur à notre position relative dans le shell, qui se termine par ".eml.gz"
la source