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

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

어떤 모듈인지 알아보려고 합니다.use Test::Versioncpan에서. 그래서 나는 사용했다minicpan그것을 반영합니다. 내 문제는 다운로드한 아카이브를 반복하고 아카이브 내의 파일을 grep해야 한다는 것입니다. 내가 어떻게 해야 하는지 누가 말해 줄 수 있나요? 아카이브의 어떤 파일이 어느 줄에 있는지 어떻게든 알려주는 것이 더 나을 것입니다.

(참고: 모두 타르볼이 아니며 일부는 zip 파일입니다.)

답변1

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

  • 텍스트 검색: 파일에서 텍스트를 검색하려면 도구가 필요합니다(예: 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=archive 이름 및 $1=search 패턴 사용).
  • $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일치하는 항목이 없으면 glob 한정자는 패턴을 빈 목록으로 확장합니다.

답변2

이건 할 수 있을 것 같아

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

이것은 타르볼의 위치에 그다지 구체적이지 않습니다. 누군가가 더 나은 답변을 줄 수 있기를 바랍니다.

답변3

우그레프옵션을 사용하여 압축 파일(gz/Z/bz2/lzma/xz/lz4/zstd) 및 아카이브(cpio/tar/pax/zip)를 반복적으로 검색합니다 -z. 옵션은 -z --zmax=2압축 파일 및 압축 파일 및 아카이브 내에 포함된 압축 파일 및 아카이브를 검색합니다(따라서 zmax=레벨 2).

답변4

어쩌면 내 대답이 누군가에게 도움이 될 수도 있습니다.

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

관련 정보