Sıkıştırılmış arşivlerde özyinelemeli olarak nasıl grep olabilirim?


16

use Test::VersionCpan'da hangi modülleri bulmaya çalışıyorum . Ben de minicpanaynısını yansıtırdım. Benim sorunum, indirilen arşivler üzerinden yineleme ve arşivlerde bulunan dosyaları grep gerekir. Birisi bana bunu nasıl yapabileceğimi söyleyebilir mi? tercihen arşivdeki hangi dosyanın ve hangi satırda olduğunu söyleyecek şekilde.

(not: hepsi tarball'lar değil, bazıları zip dosyasıdır)

Yanıtlar:


18

Tamam, unix felsefesini uygulayalım. Bu görevin bileşenleri nelerdir?

  • Metin arama: Bir dosyadaki metni aramak için bir araca ihtiyacınız vardır grep.
  • Özyinelemeli: gibi bir dizin ağacındaki dosyaları aramak için bir araca ihtiyacınız vardır find.
  • Arşivler: okumak için bir araca ihtiyacınız var.

Çoğu unix programı dosyalar üzerinde çalışır. Bu nedenle arşiv bileşenlerinde kolayca çalışmak için, onlara dosya olarak erişmeniz gerekir, başka bir deyişle onlara dizin olarak erişmeniz gerekir.

AVF'lerin dosya sistemi hediyeler her arşiv dosyası dosya sisteminin bir görünüm /path/to/foo.zipbir dizin olarak erişilebilir ~/.avfs/path/to/foo/zip#. AVFS, en yaygın arşiv dosyası biçimlerine salt okunur erişim sağlar.

mountavfs
find ~/.avfs"$PWD" \( -name '*.zip' -o -name '*.tar.gz' -o -name '*.tgz' \) \
     -exec sh -c '
                  find "$0#" -name "*.pm" -exec grep "$1" {\} +
                 ' {} 'Test::Version' \;
fusermount -u ~/.avfs   # optional

açıklamalar:

  • AVFS dosya sistemini bağlayın.
  • ~/.avfs$PWDGeçerli dizinin AVFS görünümü olan arşiv dosyalarını arayın .
  • Her arşiv için, belirtilen kabuk snippet'ini yürütün ( $0= arşiv adı ve $1= aranacak kalıpla).
  • $0#arşivin dizin görünümüdür $0.
  • {\}ziyade {}dış durumda ihtiyaç duyulan findyerine {}içindeki -exec ;argümanlar (bazı bunu, bazı yoktur).
  • İsteğe bağlı: son olarak AVFS dosya sistemini çıkarın.

Veya zsh ≥4.3 olarak:

mountavfs
grep 'Test::Version' ~/.avfs$PWD/**/*.(tgz|tar.gz|zip)(e\''
     reply=($REPLY\#/**/*.pm(.N))
'\')

açıklamalar:

  • ~/.avfs$PWD/**/*.(tgz|tar.gz|zip) geçerli dizinin ve alt dizinlerinin AVFS görünümündeki arşivlerle eşleşir.
  • PATTERN(e\''CODE'\')her PATTERN eşleşmesine CODE uygular. Eşleşen dosyanın adı $REPLY. replyDiziyi ayarlamak, eşleşmeyi bir ad listesine dönüştürür.
  • $REPLY\# arşivin dizin görünümüdür.
  • $REPLY\#/**/*.pm.pmarşivdeki dosyalarla eşleşir .
  • NEşleşme varsa desen yapar eleme glob boş listeye genişler.

bu, tüm arşivleri monte etmek ve daha sonra çıkarmak zorunda
kalmanın

@xenoterracide: Bu nasıl bir problem? AVFS ile, tek bir bağlama noktanız ( ~/.avfs) vardır ve her arşive erişim otomatiktir ( ~/.avfs/path/to/archive.zip\#AVFS dosya sistemindeki sıradan bir dizindir, bir bağlama noktası değildir). Elbette, eriştiğiniz her arşiv küçük bir performans isabeti anlamına gelir, ancak bu sorunun özüdür.
Gilles 'SO- kötü olmayı bırak'

@gilles sadece şimdi geçip bunları nasıl monte edeceğimizi bulmam gerektiği gerçeği, ki bu biraz kötü bir fikir gibi görünüyor, onları giderken monte etmek ve arandıktan sonra bağlantısını kesmek daha iyi.
xenoterracide

@xenoterracide: Tekrar: hayır, tek tek monte etmenize gerek yok. Tam iş akışı (gerekirse AVFS'yi yüklemek dışında) kod snippet'lerimde.
Gilles 'SO- kötü olmayı bırak'

@gilles iyi Bunu biraz kazmak zorunda kalacağım ... çünkü find: missing argument to -exec'i alıyorum ve bunun bir sürü zshzsh: Input/output error: Data-Maker-0.27
xenoterracide

0

Görünüşe göre bu şekilde yapabilirim

find authors/ -type f -exec zgrep "Test::Version" '{}' +  

Ancak, bu aşağıdaki gibi sonuçlar verir:

authors/id/J/JO/JONASBN/Module-Info-File-0.11.tar.gz:Binary file (standard input) matches

Tarball'daki yere çok özel değil. Umarım birisi daha iyi bir cevap bulabilir.


0

Meydan okuma için teşekkürler, ben geldim:

#!/bin/bash
#

# tarballs to check in
find authors/ -type f | while read tarball; do

    # get list of files in tarball (not dirs ending in /):
    tar tzf $tarball | grep -v '/$' | while read file; do       

        # get contents of file and look for string
        tar -Ozxf conform.tar.gz $file | grep -q 'Text::Version' && echo "Tar ($tarball) has matching File ($file)"

    done

done

Sadece hat numarası ihtiyacınızı gördüm. Bu muhtemelen satır numarasını yakalamak için grep -n ve awk'nin bazı kombinasyonlarıyla çalışabilir. Her zaman stdin olduğundan dosya adını listelemek için grep -H kadar basit olamaz, bu yüzden daha fazla satır gerektirebilir.
Kyle Smith

sistemimde çalışırken hata tar (child): conform.tar.gz: Cannot open: No such file or directory tar (child): Error is not recoverable: exiting now tar: Child returned status 2 tar: Error is not recoverable: exiting now
oluştu

Ayrıca bunu ilk yayınladığımda, cpan'daki bazı arşivlerin zip dosyaları olduğunu fark etmedim.
xenoterracide

Hm, sadece .tar.gz dosyalarının bir yapısı ile test ettim - dosya türüne göre uygun eylemleri yapmak daha sağlam hale getirilebilir, ancak bu iyi bir başlangıç ​​noktası vermelidir.
Kyle Smith

0

Belki cevabım birisi için faydalı olacaktır:

#!/bin/bash

findpath=$(echo $1 | sed -r 's|(.*[^/]$)|\1/|')

# tarballs to check in
find $findpath -type f | while read tarball; do

    # get list of files in tarball (not dirs ending in /):
    if [ -n "$(file --mime-type $tarball | grep -e "application/jar")" ]; then

        jar tf $tarball | grep -v '/$' | while read file; do
            # get contents of file and look for string
            grepout=$(unzip -q -c $tarball $file | grep $3 -e "$2")

            if [ -n "$grepout" ]; then
                echo "*** $tarball has matching file ($file):"
                echo $grepout
            fi

        done

    elif tar -tf $tarball 2>/dev/null; then

        tar -tf $tarball | grep -v '/$' | while read file; do
            # get contents of file and look for string
            grepout=$(unzip -q -c $tarball $file | grep $3 -e "$2")

            if [ -n "$grepout" ]; then
                echo "*** $tarball has matching file ($file):"
                echo $grepout
            fi

        done

    else
        file=""
        grepout=$(grep $3 -e "$2" $tarball)

        if [ -n "$grepout" ]; then
            echo "*** $tarball has matching:"
            echo $grepout
        fi

    fi

done

0

Yükledikten sonra p7zip-*bunu yapabilirsiniz:

ls | xargs -I {} 7z l {} | grep whatever | less

lsİlk kanaldan önce kullanmak zorunda değilsiniz , sıkıştırılmış dosyaların listesi ne olursa olsun çalışır. Finalde lesssadece sıkıştırılmış arşiv içindeki liste ömrünün YOLU gösterilir, ancak bunun adı gösterilmez.


0

Gerekli tüm dosyaları bulmak için find komutunu ve sıkıştırılmış dosyalara bakmak için bu zgrep komutunu kullanın:

find <folder> -type f -name "<search criteria[*gz,*bz...]>" -execdir zgrep -in "<grep expression>" '{}' ';'

Yine de tarballs üzerinde test etmedi

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.