압축 된 아카이브를 재귀 적으로 파악하는 방법은 무엇입니까? 아카이브를 반복하고 아카이브에있는 파일을

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

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



답변

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

  • 텍스트 검색 :과 같은 파일에서 텍스트를 검색하는 도구가 필요합니다 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일치가없는 경우 패턴을 만드는 규정 글로브 빈 목록을 확장합니다.

답변

이런 식으로 할 수있는 것 같습니다

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

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


답변

도전 해 주셔서 감사합니다.

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

답변

어쩌면 내 대답은 누군가에게 도움이 될 것입니다.

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

답변

설치 후 p7zip-*다음을 수행 할 수 있습니다.

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

ls압축 파일이 작동하는 목록에 관계없이 첫 번째 파이프 전에는 사용할 필요가 없습니다 . 마지막 less은 압축 된 아카이브 내의 목록 수명의 PATH 만 표시하지만이 이름은 표시하지 않습니다.


답변

find를 사용하여 필요한 모든 파일을 찾고 해당 zgrep를 사용하여 압축 파일을 찾으십시오.

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

tarballs에서 이것을 테스트하지 않았습니다.