Tekrarlı olarak .gz dosyaları ile nasıl grep yapabilirim?


135

Ham .eml dosyasını .gz dosyalarına sıkıştıran gmail iletilerimi düzenli olarak indirmek için bir komut dosyası kullanıyorum. Komut dosyası her gün için bir klasör oluşturur ve ardından her mesajı kendi dosyasına sıkıştırır.

Bu arşivde bir "string" aramak için bir yol istiyorum.

Grep yalnız yapmak için görünmüyor. Ayrıca SearchMonkey'i de denedim.


16
kullanın zgrep:zgrep - search possibly compressed files for a regular expression
Arkadiusz Drabczyk

Yanıtlar:


141

Geçerli dizindeki tüm .eml.gz dosyalarında yinelemeli bir şekilde grep yapmak istiyorsanız, şunları kullanabilirsiniz:

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

İlkinden kaçmalısın, *böylece kabuk onu yorumlamaz. -print0bulduğu her bir dosyadan sonra boş bir karakter yazdırmayı; xargs -0standart girdiden okur ve her dosya için ondan sonra komutu çalıştırır; zgrepgibi çalışır grep, ancak önce dosyayı açar.


2
'-print0' ve '-0' zorunlu değildir. xargs varsayılan olarak '\ n' kullanır.
Jaime M.

1
Yollarda boşluk karakterleri olabilirse gerekli olurlar; Karmaşıklıktan başka, onları kullanmamak için hiçbir sebep yoktur.
Daniel Griscom

2
zgrepAslında grep, sıkıştırılmamış dosyalar üzerinde çalıştırmaktan daha hızlı görünüyor . Bunun nedeni sıkıştırılmış dosyaların HD'den okunabilmesi ve HD'den sıkıştırılmamış bir dosyayı okumaktan daha hızlı bir şekilde açılabilmesidir.
Geremia

@JaimeM. varsayılan olarak boşlukları (boşluk) xargskullanır . Elbette, dosyalar neredeyse hiçbir zaman içlerinde yeni satırlar içermezler, ancak boşluklar duyulmamış değildir (çoğu UNIXy türü üzerini çizse bile). Bununla birlikte, beyaz alandan endişe duymadan daha kolay bir şekilde kolaylaştırabilirsiniz: Bu, lansman başına / / ' nın güvenliği ve aynı zamanda ekstra bir işlem lansmanı ve boru tesisatı yükü olmadan pek çok argüman alır ve oldukça öz bir şekilde. ile POSIX belirtilen, bu yüzden bildiğim kadarıyla en yarı son UNIX benzeri sistemlerde olmalıdır. find . -name '*.eml.gz' -exec zgrep "STRING" {} +xargs-print0-0-exec+
ShadowRanger

@Jared Sadece dosya modelinin başlangıcını bilerek bir joker arama yapmanın bir yolu var mı? Örneğin, sonunda tarih / saat damgası olan .gz dosyalarım var. ABCLog04_18_18_2_21.gz Sürekli olarak ABC * ile başlayan dosyaları aramanın bir yolu var mı? \*.eml.gzYukarıdaki örnekte değiştirmeyi ABCLog*ve dosya formatıyla ilgili bir hata almayı denedim . :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

Burada çok fazla karışıklık var çünkü sadece bir tane yok zgrep. Benim sistemde iki sürümü vardır zgrepden gzipve zgrepdan zutils. İlki, çağıran yalnızca bir sarmalayıcı komut dosyasıdır gzip -cdfq. -r, --recursiveAnahtarı desteklemiyor . 1
ikincisi bir olan c++programı ve destekler-r, --recursive seçeneği.
Koşu zgrep --version | head -n 1, hangisinin (varsa) varsayılanı olduğunu ortaya çıkarır:

zgrep (gzip) 1.6

sarıcı komut dosyası

zgrep (zutils) 1.3

olan cppçalıştırılabilir.
İkincisi varsa koşabilirsiniz:

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

Yine de, önerildiği gibi, find+ aşağıdakilerden zgrepbiriyle eşit derecede iyi çalışacaktır zgrep:

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

Eğer zgrepsizinle deneyebilirsiniz (yüksek ihtimal) sisteminizden eksik:

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

ancak büyük bir dezavantajı var: eşleşen satırlara önceden hazırlanmış bir dosya adı olmadığı için kibritlerin nerede olduğunu bilemezsiniz.


1: çünkü sorunlu olurdu


1
eğer zgrepzutils ulaşılabilir değil sen ile Ubuntu yükleyebilirsiniz sudo apt-get install zutils.
therealmarv

1
@Therealmarv'dan devam ... ve sonra Ubuntu, gzip yerine zutils zgrep kullanacaktır. O zaman -r çalışıyor!
Elijah Lynn

Desenin eşleştiği dosyanın satır numarasını yazdırmanın bir yolu var mı?
DogEatDog

@DogEatDog - tıpkı grep -n, zgrep -nsatır no.s. El kitabında ...
don_crissti 9:17

7

aggrepBazı güzel ekstra özelliklere sahip , bir çeşididir .

  • sıkıştırılmış dosyalar için -z seçeneğine sahiptir,
  • birçok ack özelliğine sahiptir.
  • o hızlı

Yani:

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

Takılı değilse

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

1
ag: truncated file: SuccessSonuç olarak alıyorum . Başka bir bayrak eklemem gerekir mi?
Yar

4

Tek başına özyineleme kolaydır:

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

Ancak, sıkıştırılmış dosyalar için şöyle bir şeye ihtiyacınız vardır:

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

path/to/directory Her gün için alt dizinleri içeren ana dizin olmalıdır.


zgrepbariz cevap, ancak maalesef -rbayrağı desteklemiyor . Kimden man zgrep:

Bunlar grep seçenekleri bir hata kodu ile sona erdirmek zgrep neden olur: (- [d rR ZZ] | --di * | --exc * | --inc * | --rec * | --nu *).


3

Sisteminizde zgrep varsa, basitçe

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

Sisteminizde zgrep yoksa, zcat komutunu çalıştırmak ve her dosyaya karşı grep uygulamak için find komutunu kullanabilirsiniz :

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


Bu konuda yeşillikle beni bağışlayın ... aranacak dosyalar birkaç kat derinliktedir. ~ / gmvault-db / db / 2015-02, arşivlenen her ay için bir klasör ve ardından o ayın .gz dosyalarının saklandığı bir klasör içerir. Bütün ağacın içinde .mil ararsam, yapacağım şey bu mu? ~ / gmvault-db / db / -adı '* .gz' \ -exec sh -c 'echo "{}" aranıyor; zcat "{}" | grep .mil '\;
Kendor

1
Sorun değil - 'r' ifadesi zgrep'in tekrarlı arama yapmasına neden olacak. Find komutu varsayılan olarak yinelemeli olarak çalışır, bu nedenle .gz ile biten herhangi bir dosya yakalanır ve grep'e aktarılır. (ve {}, aranacak olan dosyanın görece yoluna genişletilecektir). Böylece bir hit aldığınızda, bundan önce Searching ~/gmvault-db/db/2015-02/03/whatever.gz
gelenler

İşte geri döndüğüm şey: find: "yollar ifadeden önce gelmeli: -exec" İşte kullandığım komut: find ~ / gmvault-db / db / -name '* .gz' \ -exec sh -c 'echo "Arama { } "; zcat "{}" | grep .mil '\;
Kendor

'* .gz' ve -exec arasındaki ters eğik çizgiyi çıkarın.
Kalamazoo'dan Nate

4
zgrepbir -rsebepten ötürü bayrağı almayacak . Bu da bahsetti man zgrep(cevabımı da gör).
terdon

0

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

xzgrep, zgrep utils'in bir türevidir (less / bin / xzgrep)

Man sayfasından:

xzgrep, sıkıştırılmamış veya xz (1), lzma (1), gzip (1), bzip2 (1) veya lzop (1) ile sıkıştırılmış olabilecek dosyalar üzerinde grep'i (1) çağırır. Belirtilen tüm seçenekler doğrudan grep'e (1) geçirilir.

-Ben eşleşen dosya adını yazdırabilirim

- Özyinelemede R, komut dosyasında özellikle yasak olduğu için çalışmayacak, ancak basit kabarıklıklar bizi oraya götürmeli

./*/*.eml.gz

./today/sample.eml.gz'nin tüm örnekleriyle eşleştiği, ".eml.gz" ile biten, kabuktaki göreceli konumumuzun bir seviyesinin altında olduğu göreceli bir yoldan

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.