ฉันจะ grep ซ้ำโดยใช้ไฟล์เก็บถาวรที่บีบอัดได้อย่างไร


16

ฉันพยายามค้นหาโมดูลuse Test::Versionใน cpan ดังนั้นฉันจึงเคยminicpanสะท้อนมัน ปัญหาของฉันคือฉันต้องวนซ้ำไฟล์เก็บถาวรที่ดาวน์โหลดมาและ grep ไฟล์ที่อยู่ในไฟล์เก็บถาวร มีใครบอกฉันได้ไหมว่าฉันจะทำเช่นนี้? ควรเป็นวิธีที่บอกฉันว่าไฟล์ใดในไฟล์เก็บถาวรและบรรทัดใดที่เปิดอยู่

(หมายเหตุ: ไฟล์เหล่านี้ไม่ใช่ไฟล์ tarball ทั้งหมดเป็นไฟล์ซิป)

คำตอบ:


18

เอาล่ะมาใช้ปรัชญา unix กันดีกว่า องค์ประกอบของงานนี้คืออะไร?

  • การค้นหาข้อความ: คุณต้องการเครื่องมือในการค้นหาข้อความในไฟล์เช่น grepคุณต้องการเครื่องมือในการค้นหาข้อความในไฟล์เช่น
  • แบบเรียกซ้ำ: คุณต้องใช้เครื่องมือเพื่อค้นหาไฟล์ในแผนผังไดเรกทอรีเช่น findคุณต้องการเครื่องมือที่จะไปมองหาไฟล์ในต้นไม้ไดเรกทอรีเช่น
  • คลังเก็บ: คุณต้องการเครื่องมือในการอ่าน

โปรแกรม unix ส่วนใหญ่ทำงานกับไฟล์ ดังนั้นในการทำงานกับส่วนประกอบที่เก็บถาวรได้ง่ายคุณจำเป็นต้องเข้าถึงมันเป็นไฟล์หรือกล่าวอีกนัยหนึ่งว่าคุณต้องเข้าถึงมันในรูปของไดเร็กตอรี่

AVFSระบบแฟ้มนำเสนอมุมมองของระบบแฟ้มที่ทุกไฟล์เก็บถาวรสามารถเข้าถึงได้เป็นไดเรกทอรี/path/to/foo.zip ~/.avfs/path/to/foo/zip#AVFS จัดให้มีการเข้าถึงรูปแบบไฟล์เก็บถาวรทั่วไปอย่างมาก

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

คำอธิบาย:

  • เมานต์ระบบไฟล์ AVFS
  • ค้นหาไฟล์เก็บถาวร~/.avfs$PWDซึ่งเป็นมุมมอง AVFS ของไดเรกทอรีปัจจุบัน
  • สำหรับแต่ละไฟล์เก็บถาวรให้ดำเนินการตัวอย่างเชลล์ที่ระบุ (ด้วย$0ชื่อ = ไฟล์เก็บถาวรและ$1รูปแบบ = เพื่อค้นหา)
  • $0#$0เป็นมุมมองของไดเรกทอรีที่เก็บ
  • {\}แทนที่จะ{}ต้องการในกรณีที่การfindแทนที่ภายนอก{}ภายใน-exec ;อาร์กิวเมนต์ (บางคนทำมันบางคนไม่ได้)
  • ทางเลือก: ในที่สุดก็ยกเลิกการต่อเชื่อมระบบไฟล์ AVFS

หรือใน zsh ≥4.3:

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

คำอธิบาย:

  • ~/.avfs$PWD/**/*.(tgz|tar.gz|zip) จับคู่ไฟล์เก็บถาวรในมุมมอง AVFS ของไดเร็กทอรีปัจจุบันและไดเร็กทอรีย่อย
  • PATTERN(e\''CODE'\')ใช้รหัสกับการแข่งขันแต่ละแบบ $REPLYชื่อของแฟ้มที่ตรงกับที่อยู่ใน การตั้งค่าreplyอาร์เรย์เปลี่ยนการจับคู่ให้เป็นรายการของชื่อ
  • $REPLY\# คือมุมมองไดเร็กทอรีของไฟล์เก็บถาวร
  • $REPLY\#/**/*.pmจับคู่.pmไฟล์ในไฟล์เก็บถาวร
  • ตัวระบุแบบNหมุนทำให้รูปแบบขยายเป็นรายการที่ว่างเปล่าหากไม่มีการจับคู่

สิ่งนี้สร้างปัญหาที่น่าสนใจอื่น ๆ ของการเมานต์แล้วเลิกเมานท์คลังข้อมูลทั้งหมดซึ่งเป็นส่วนหนึ่งของปัญหาคือมีคลังเก็บ 22k ที่ต้องค้นหาผ่าน
xenoterracide

@xenoterracide: นั่นเป็นปัญหาได้อย่างไร ด้วย AVFS คุณจะมีจุดเชื่อมต่อจุดเดียว ( ~/.avfs) และการเข้าถึงแต่ละไฟล์เก็บถาวรเป็นไปโดยอัตโนมัติ ( ~/.avfs/path/to/archive.zip\#เป็นไดเรกทอรีทั่วไปบนระบบไฟล์ AVFS ไม่ใช่จุดเชื่อมต่อ) แน่นอนว่าการเก็บถาวรแต่ละรายการที่คุณเข้าถึงหมายถึงประสิทธิภาพที่เล็กน้อย แต่ก็เป็นปัญหาที่แท้จริง
Gilles 'หยุดชั่วร้าย'

@gilles ความจริงที่ว่าตอนนี้ฉันต้องผ่านและคิดหาวิธีการติดพวกเขาก่อนซึ่งดูเหมือนว่าเป็นความคิดที่ไม่ดีควรติดพวกเขาเมื่อฉันไปและถอนการติดตั้งหลังจากการค้นหา
xenoterracide

@xenoterracide: อีกครั้ง: ไม่คุณไม่จำเป็นต้องติดตั้งทีละรายการ เวิร์กโฟลว์เต็มรูปแบบ (นอกเหนือจากการติดตั้ง AVFS หากจำเป็น) อยู่ในข้อมูลโค้ดของฉัน
Gilles 'หยุดความชั่วร้าย'

@gilles ดีฉันจะต้องขุดลงไปในนี้เล็กน้อย ... เพราะฉันได้รับfind: missing argument to -exec'` และจำนวนมากจาก zshzsh: Input/output error: Data-Maker-0.27
xenoterracide

0

ดูเหมือนว่าฉันจะทำแบบนี้

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

อย่างไรก็ตามสิ่งนี้ให้ผลลัพธ์ดังนี้:

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

ซึ่งไม่เฉพาะเจาะจงมากกับที่อยู่ใน tarball หวังว่าบางคนจะได้คำตอบที่ดีกว่า


0

ขอบคุณสำหรับความท้าทายฉันมาด้วย:

#!/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

เพิ่งเห็นความต้องการหมายเลขบรรทัดของคุณ ที่สามารถทำงานร่วมกับ grep -n และ awk เพื่อจับหมายเลขบรรทัดได้ ไม่สามารถเรียบง่ายเหมือน grep -H เพื่อแสดงรายการชื่อไฟล์เนื่องจากเป็น stdin เสมอดังนั้นอาจต้องใช้บรรทัดเพิ่มเติม
Kyle Smith

ข้อผิดพลาดเมื่อทำงานในระบบของฉันซ้ำไม่สิ้นสุด: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

ฉันก็ไม่รู้เหมือนกันเมื่อฉันโพสต์สิ่งนี้ครั้งแรกว่าไฟล์เก็บถาวรบางไฟล์ใน cpan เป็นไฟล์ zip
xenoterracide

หืมมฉันทดสอบด้วยโครงสร้างของไฟล์. tar.gz เท่านั้น - มันอาจทำให้มีประสิทธิภาพมากขึ้นในการดำเนินการตามประเภทของไฟล์ที่เหมาะสม แต่สิ่งนี้ควรเป็นจุดเริ่มต้นที่ดี
Kyle Smith

0

บางทีคำตอบของฉันจะเป็นประโยชน์สำหรับใครบางคน:

#!/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

หลังจากติดตั้งp7zip-*คุณสามารถทำสิ่งนี้:

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

คุณไม่จำเป็นต้องใช้งานlsก่อนไปป์แรกรายการใดก็ตามที่ไฟล์บีบอัดจะทำงาน สุดท้ายlessเท่านั้นที่จะแสดงเส้นทางของชีวิตของชุดรายการภายในเก็บถาวรบีบอัด แต่ไม่ได้ชื่อของสิ่งนี้


0

ใช้ find เพื่อค้นหาไฟล์ที่จำเป็นทั้งหมดและ zgrep นั้นเพื่อค้นหาไฟล์บีบอัด:

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

ไม่ได้ทดสอบสิ่งนี้ใน tarballs

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.