Bagaimana cara saya secara rekeptif memahami arsip terkompresi?

16

Saya mencoba mencari tahu modul apa yang ada use Test::Versiondi cpan. Jadi saya telah menggunakan minicpancermin itu. Masalah saya adalah bahwa saya perlu mengulangi arsip yang diunduh, dan mengambil file yang ada di arsip. Adakah yang bisa memberitahu saya bagaimana saya bisa melakukan ini? lebih disukai dengan cara yang memberi tahu saya file mana dalam arsip dan baris apa yang aktif.

(catatan: mereka tidak semua tarbal, ada juga file zip)

xenoterracide
sumber

Jawaban:

18

Ok, mari kita terapkan filosofi unix. Apa komponen dari tugas ini?

  • Pencarian teks: Anda memerlukan alat untuk mencari teks dalam file, seperti grep.
  • Rekursif: Anda memerlukan alat untuk mencari file di pohon direktori, seperti find.
  • Arsip: Anda memerlukan alat untuk membacanya.

Sebagian besar program unix beroperasi pada file. Jadi untuk beroperasi dengan mudah pada komponen arsip, Anda perlu mengaksesnya sebagai file, dengan kata lain Anda perlu mengaksesnya sebagai direktori.

Sistem file AVFS menyajikan tampilan sistem file tempat setiap file arsip /path/to/foo.zipdapat diakses sebagai direktori ~/.avfs/path/to/foo/zip#. AVFS menyediakan akses hanya baca ke sebagian besar format file arsip.

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

Penjelasan:

  • Pasang sistem file AVFS.
  • Cari file arsip di ~/.avfs$PWD, yang merupakan tampilan AVFS dari direktori saat ini.
  • Untuk setiap arsip, jalankan cuplikan shell yang ditentukan (dengan $0= nama arsip dan $1= pola untuk dicari).
  • $0#adalah tampilan direktori arsip $0.
  • {\}daripada {}diperlukan jika findpengganti luar {}dalam -exec ;argumen (beberapa melakukannya, beberapa tidak).
  • Opsional: akhirnya unmount sistem file AVFS.

Atau dalam zsh ≥4.3:

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

Penjelasan:

  • ~/.avfs$PWD/**/*.(tgz|tar.gz|zip) cocok dengan arsip dalam tampilan AVFS direktori saat ini dan subdirektori.
  • PATTERN(e\''CODE'\')berlaku KODE untuk setiap kecocokan POLA. Nama file yang cocok ada di $REPLY. Mengatur replyarray mengubah kecocokan menjadi daftar nama.
  • $REPLY\# adalah tampilan direktori arsip.
  • $REPLY\#/**/*.pmcocok dengan .pmfile dalam arsip.
  • The Ngumpal kualifikasi membuat pola memperluas untuk daftar kosong jika tidak ada pertandingan.
Gilles 'SANGAT berhenti menjadi jahat'
sumber
ini menciptakan masalah menarik lainnya karena harus memasang dan kemudian meng-unmount semua arsip, karena bagian dari masalahnya adalah bahwa ada 22k arsip yang perlu dicari melalui
xenoterracide
@xenoterracide: Bagaimana itu menjadi masalah? Dengan AVFS, Anda memiliki satu titik pemasangan ( ~/.avfs), dan akses ke setiap arsip otomatis ( ~/.avfs/path/to/archive.zip\#adalah direktori biasa pada sistem file AVFS, bukan titik pemasangan). Tentu, setiap arsip yang Anda akses berarti sedikit performa, tetapi itu intrinsik untuk masalah tersebut.
Gilles 'SANGAT berhenti menjadi jahat'
@Gilles hanya fakta bahwa sekarang saya harus melalui dan mencari cara untuk me-mount mereka terlebih dahulu, yang sepertinya sedikit ide yang buruk, lebih baik untuk me-mount mereka ketika saya pergi dan unmount setelah dicari.
xenoterracide
@ xenoterracide: Sekali lagi: tidak, Anda tidak perlu me-mount secara individual. Alur kerja lengkap (selain menginstal AVFS jika perlu) ada dalam cuplikan kode saya.
Gilles 'SANGAT berhenti menjadi jahat'
@ Gilles yah saya harus menggali sedikit ini ... karena saya mendapatkan find: missing argument to -exec'` dan banyak dari ini dari zshzsh: Input/output error: Data-Maker-0.27
xenoterracide
0

Tampaknya saya bisa melakukannya dengan cara ini

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

Namun, ini memberikan hasil seperti:

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

yang tidak terlalu spesifik ke tempat di tarball. Semoga seseorang dapat memberikan jawaban yang lebih baik.

xenoterracide
sumber
0

Terima kasih atas tantangannya, saya datang dengan:

#!/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
Kyle Smith
sumber
Baru saja melihat persyaratan nomor baris Anda. Itu mungkin dapat bekerja dengan beberapa kombinasi grep -n dan awk untuk menangkap nomor baris. Tidak dapat sesederhana grep -H untuk membuat daftar nama file karena selalu stdin, jadi mungkin memerlukan lebih banyak baris.
Kyle Smith
kesalahan keluar ketika dijalankan pada sistem saya, infinite diulang: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
xenoterracide
juga saya tidak menyadari ketika saya pertama kali memposting ini bahwa beberapa arsip di cpan adalah file zip.
xenoterracide
Hm, saya menguji dengan struktur hanya file .tar.gz - bisa dibuat lebih kuat untuk mengambil tindakan yang sesuai berdasarkan tipe file, tetapi ini harus memberikan titik awal yang layak.
Kyle Smith
0

Mungkin jawaban saya akan membantu seseorang:

#!/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
Serge Roussak
sumber
0

Setelah menginstal, p7zip-*Anda dapat melakukan ini:

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

Anda tidak harus menggunakan lssebelum pipa pertama, apa pun daftar file terkompresi akan berfungsi. Final lesshanya akan menampilkan PATH dari kehidupan listet di dalam arsip terkompresi, tetapi bukan nama ini.

Roberto Robert
sumber
0

Gunakan find untuk menemukan semua file yang diperlukan, dan zgrep untuk melihat file terkompresi:

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

Tidak menguji ini di tarbal

Iggy Pop
sumber