압축 된 아카이브를 재귀 적으로 파악하는 방법은 무엇입니까?


16

use Test::Versioncpan의 어떤 모듈을 찾으려고합니다 . 그래서 나는 minicpan그것을 미러링하는 데 사용 했습니다. 내 문제는 다운로드 된 아카이브를 반복하고 아카이브에있는 파일을 grep해야한다는 것입니다. 아무도 내가 어떻게 할 수 있는지 말해 줄 수 있습니까? 바람직하게는 아카이브의 어떤 파일과 어떤 줄에 있는지 알려줍니다.

(참고 : 일부 zip 파일이 아닌 일부는 zip 파일입니다)

답변:


18

좋아, 유닉스 철학을 적용하자. 이 작업의 구성 요소는 무엇입니까?

  • 텍스트 검색 :과 같은 파일에서 텍스트를 검색하는 도구가 필요합니다 grep.
  • 재귀 : 디렉토리 트리에서 파일을 찾는 도구가 필요합니다 (예 :) find.
  • 아카이브 : 읽을 도구가 필요합니다.

대부분의 유닉스 프로그램은 파일에서 작동합니다. 따라서 아카이브 구성 요소에서 쉽게 작동하려면 파일로 액세스해야합니다. 다시 말해 디렉토리로 액세스해야합니다.

에서 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'\')PATTERN의 각 일치에 CODE를 적용합니다. 일치하는 파일의 이름은입니다 $REPLY. reply배열을 설정하면 일치 항목이 이름 목록으로 바뀝니다.
  • $REPLY\# 아카이브의 디렉토리보기입니다.
  • $REPLY\#/**/*.pm.pm아카이브의 파일 과 일치 합니다.
  • N일치가없는 경우 패턴을 만드는 규정 글로브 빈 목록을 확장합니다.

이 마운트해야하는 다른 intesting 문제를 만든 다음, 아카이브의 모든 마운트 해제 문제가 필요 통해 검색 할 것을 22K 아카이브가 있다는 것입니다의 일환으로
xenoterracide

@ xenoterracide : 어떻게 문제가 있습니까? AVFS를 사용하면 단일 마운트 지점 ( ~/.avfs)이 있으며 각 아카이브에 대한 액세스는 자동입니다 ( ~/.avfs/path/to/archive.zip\#마운트 지점이 아닌 AVFS 파일 시스템의 일반 디렉토리 임). 물론, 액세스하는 각 아카이브는 약간의 성능 저하를 의미하지만 문제의 본질입니다.
Gilles 'SO- 악마 그만해'

@ 아저씨는 이제 내가 먼저 마운트하는 방법을 알아 내야한다는 사실 만 알고 있습니다. 조금 나쁜 생각 인 것처럼 보이며 검색 후 마운트를 풀고 마운트를 해제하는 것이 좋습니다.
xenoterracide

@xenoterracide : 다시 : 아니요, 개별적으로 마운트 할 필요는 없습니다. 전체 워크 플로우 (필요한 경우 AVFS 설치 제외)는 내 코드 스 니펫에 있습니다.
Gilles 'SO- 악마 그만'

@gilles 잘 나는 이것에 대해 조금 파헤쳐 야 할 것이다. 왜냐하면 find: missing argument to -exec '를 얻었 기 때문이다. 그리고 zsh로부터 이것의 많은zsh: 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

타르볼의 위치에 따라 다르지 않습니다. 잘하면 누군가가 더 나은 대답을 얻을 수 있기를 바랍니다.


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의 조합으로 행 번호를 캡처 할 수 있습니다. 파일 이름이 항상 stdin이므로 grep -H만큼 간단하지 않아 파일 이름이 더 많으므로 더 많은 줄이 필요할 수 있습니다.
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은 압축 된 아카이브 내의 목록 수명의 PATH 만 표시하지만이 이름은 표시하지 않습니다.


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.