Farklı arşiv formatlarındaki tüm arşiv dosyalarını özyinelemeli olarak bulun ve dosya adı kalıplarını arayın


11

En iyi ben böyle bir çağrı istiyorum:

$searchtool /path/to/search/ -contained-file-name "*vacation*jpg"

... böylece bu araç

  • verilen yolun yinelemeli taramasını yapar
  • en azından zip, rar, 7z, tar.bz, tar.gz gibi "en yaygın" olması gereken desteklenen arşiv formatlarına sahip tüm dosyaları alır ...
  • ve söz konusu ad deseni için arşivin dosya listesini tarayın (burada *vacation*jpg)

Bulma aracını, katranı, sıkıştırmayı açmayı ve benzerlerini nasıl kullanacağımı biliyorum. Bu bir kabuk komut dosyası ile birleştirmek olabilir ama bir kabuk bir astar veya özel bir araç olabilir basit bir çözüm arıyorum (GUI araçlarına ipuçları bekliyoruz ama benim çözüm komut satırı tabanlı olmalıdır).

Yanıtlar:


9

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

Arşivlerin içinde şeffaf erişim sağlayan bir dosya sistemi olan AVFS'yi yükleyin . İlk olarak, makinenizin dosya sisteminin arşivlere dizinmiş gibi erişebileceğiniz bir görünümünü ayarlamak için bu komutu bir kez çalıştırın:

mountavfs

Bundan sonra, /path/to/archive.ziptanınan bir arşiv ~/.avfs/path/to/archive.zip#ise, arşivin içeriğini içerdiği görünen bir dizindir.

find ~/.avfs"$PWD" \( -name '*.7z' -o -name '*.zip' -o -name '*.tar.gz' -o -name '*.tgz' \) \
     -exec sh -c '
                  find "$0#" -name "*vacation*.jpg"
                 ' {} 'Test::Version' \;

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

Veya zsh ≥4.3 olarak:

mountavfs
ls -l ~/.avfs$PWD/**/*.(7z|tgz|tar.gz|zip)(e\''
     reply=($REPLY\#/**/*vacation*.jpg(.N))
'\')

açıklamalar:

  • ~/.avfs$PWD/**/*.(7z|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\#/**/*vacation*.jpg*vacation*.jpgarşivdeki dosyalarla eşleşir .
  • NEşleşme varsa desen yapar eleme glob boş listeye genişler.

9

AVFS çözümünden daha basit bir şey istiyorsanız, bunu yapmak için arkfind adında bir Python betiği yazdım . Aslında yapabilirsin

$ arkfind /path/to/search/ -g "*vacation*jpg"

Bunu yinelemeli olarak yapar, böylece arşivlerin içindeki arşivlere keyfi bir derinliğe bakabilirsiniz.


Teşekkürler, güzel katkı! Özellikle AVFS bir seçenek değilse.
mdo

Jar dosyalarını desteklemesi harika olurdu.
Chemik

@Chemik - kaydetti ! Bu hafta sonu biraz daha çalışacağım :) JAR çok zor olmamalı, gerçekten dış dünyaya sadece bir zip dosyası olduğuna inanıyorum.
kibirli

@Chemik - Sadece denedim ve JAR dosyalarını şu anki haliyle desteklemeli. Test edebilir ve beklediğiniz gibi çalışmazsa, Github sayfasında bir hata dosyası hazırlayabilir misiniz? (Sadece bir hatayı düzelttim, bu yüzden kopyanızı güncellediğinizden emin olun.)
2013'te

1
Evet şimdi görüyorum, işe yarıyor. README'e "JAR dosyaları" ekleyebilirsiniz :)
Chemik

2

Her zamanki çözümüm:

find -iname '*.zip' -exec unzip -l {} \; 2>/dev/null | grep '\.zip\|DESIRED_FILE_TO_SEARCH'

Misal:

find -iname '*.zip' -exec unzip -l {} \; 2>/dev/null | grep '\.zip\|characterize.txt'

Resuls şöyle:

foozip1.zip:
foozip2.zip:
foozip3.zip:
    DESIRED_FILE_TO_SEARCH
foozip4.zip:
...

Sadece isabetli zip dosyasını istiyorsanız:

find -iname '*.zip' -exec unzip -l {} \; 2>/dev/null | grep '\.zip\|FILENAME' | grep -B1 'FILENAME'

Burada FILENAME iki kez kullanıldığından bir değişken kullanabilirsiniz.

Bul ile PATH / TO / SEARCH kullanabilirsiniz


2

Çalışan başka bir çözüm zgrep

zgrep -r filename *.zip

1
Bu nasıl bir uygulama zgrep? GNU gzip( /bin/zgrep: -r: option not supported, zgrep (gzip) 1.6) ile gönderilenle çalışmaz
Stéphane Chazelas

2

IMHO kullanıcı dostu olması bash'da da bir şey olmalı:

 while read -r zip_file ; do echo "$zip_file" ; unzip -l "$zip_file" | \
 grep -i --color=always -R "$to_srch"; \
 done < <(find . \( -name '*.7z' -o -name '*.zip' \)) | \
 less -R

ve katran için (bu test edilmemiştir ...)

 while read -r tar_file ; do echo "$tar_file" ; tar -tf  "$tar_file" | \
 grep -i --color=always -R "$to_srch"; \
 done < <(find . \( -name '*.tar.gz' -o -name '*.tar' \)) | \
 less -R

Hangi unzipuygulama 7z veya tar.gz dosyalarıyla başa çıkabilir?
Stéphane Chazelas

evet bu bir hata ... düzeltildi ... biri doğru dosya türleri için kesinlikle doğru ikili dosyaları kullanmalıyım ... Ben sadece bir astar göstermek istedim .. jee bu neredeyse hazır olma durumuna alacak nasıl yapılır makbuzu ...
Yordan Georgiev

0

libarchive's bsdtarbu dosya biçimlerinin çoğunu işleyebilir, böylece şunları yapabilirsiniz:

find . \( -name '*.zip' -o     \
          -name '*.tar' -o     \
          -name '*.tar.gz' -o  \
          -name '*.tar.bz2' -o \
          -name '*.tar.xz' -o  \
          -name '*.tgz' -o     \
          -name '*.tbz2' -o    \
          -name '*.7z' -o      \
          -name '*.iso' -o     \
          -name '*.cpio' -o    \
          -name '*.a' -o       \
          -name '*.ar' \)      \
       -type f                 \
       -exec bsdtar tf {} '*vacation*jpg' \; 2> /dev/null

GNU findile basitleştirebileceğiniz (ve büyük / küçük harfe duyarlı olmayan şekilde eşleştirebileceğiniz) :

find . -regextype egrep \
       -iregex '.*\.(zip|7z|iso|cpio|ar?|tar(|\.[gx]z|\.bz2)|tgz|tbz2)' \
       -type f \
       -exec bsdtar tf {} '*vacation*jpg' \; 2> /dev/null

Bu, bu *vacation*jpgdosyaların bulunduğu arşiv yolunu yazdırmaz . Bu adı yazdırmak için son satırı aşağıdakilerle değiştirebilirsiniz:

-exec sh -ac '
   for ARCHIVE do
     bsdtar tf "$ARCHIVE" "*vacation*jpg" |
       awk '\''{print ENVIRON["ARCHIVE"] ": " $0}'\''
   done' sh {} + 2> /dev/null

hangi gibi bir çıktı verir:

./a.zip: foo/blah_vacation.jpg
./a.zip: bar/blih_vacation.jpg
./a.tar.gz: foo/blah_vacation.jpg
./a.tar.gz: bar/blih_vacation.jpg

Veya zsh:

setopt extendedglob # best in ~/.zshrc
for archive (**/*.(#i)(zip|7z|iso|cpio|a|ar|tar(|.gz|.xz|.bz2)|tgz|tbz2)(.ND)) {
  matches=("${(f@)$(bsdtar tf $archive '*vacation*jpg' 2> /dev/null)"})
  (($#matches)) && printf '%s\n' "$archive: "$^matches
}

Sadece bir dizi başka dosya formatı zipveya tgzkılık değiştirmiş dosyalar .jarveya .docxdosyalar olduğunu unutmayın. Bunları find/ zsharama deseninize ekleyebilirsiniz bsdtar, uzantıyı umursamazsınız (dosyada olduğu gibi, dosyanın türünü belirlemek için uzantıya güvenmez).

O Not *vacation*.jpgÜzerinde eşleşir nedenle yukarıdaki, tam arşiv üye yolunda değil, sadece dosya adını eşleşir vacation.jpgda ancak vacation/2014/file.jpg.

Yalnızca dosya adıyla eşleşmek için, bir hile ayıklama modunu kullanmak , eşleşen dosyaların adlarını yazdırmak için -sbir pişaretle regexps kullanan (ikame) kullanın ve ardından hiçbir dosyanın ayıklanmadığından emin olun:

bsdtar -'s|.*vacation[^/]*$||' -'s|.*||' -xf "$archive"

Listenin stderr üzerindeki çıktısının alınacağını ve >>her satıra ekleneceğini unutmayın . Her durumda, bsdtarçoğu taruygulama gibi, satırsonu veya ters eğik çizgi ( \nveya olarak işlenir \\) gibi bazı karakterler içeriyorsa ekrandaki dosya adlarını değiştirebilir .

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.