다양한 아카이브 형식의 모든 아카이브 파일을 재귀 적으로 찾고 파일 이름 패턴을 검색하십시오. 대한 아카이브의

기껏해야 다음과 같은 전화를하고 싶습니다 :

$searchtool /path/to/search/ -contained-file-name "*vacation*jpg"

…이 도구는

  • 주어진 경로의 재귀 스캔을 수행
  • 최소한 zip, rar, 7z, tar.bz, tar.gz와 같은 “가장 일반적”이어야하는 지원되는 아카이브 형식의 모든 파일을 가져옵니다.
  • 해당 이름 패턴에 대한 아카이브의 파일 목록을 스캔하십시오 (여기에서 *vacation*jpg).

찾기 도구, tar, unzip 등을 사용하는 방법을 알고 있습니다. 나는 이것을 쉘 스크립트와 결합 할 수는 있지만 쉘 one-liner 또는 전용 도구 일 수있는 간단한 솔루션을 찾고 있습니다 (GUI 도구에 대한 힌트는 환영하지만 솔루션은 명령 줄 기반이어야합니다).



답변

( 압축 된 아카이브를 재귀 적으로 가져 오는 방법은 무엇입니까? )

아카이브 내에서 투명한 액세스를 제공하는 파일 시스템 인 AVFS를 설치 하십시오 . 먼저이 명령을 한 번 실행하여 아카이브처럼 디렉토리에 액세스 할 수있는 시스템의 파일 시스템보기를 설정하십시오.

mountavfs

그런 다음, /path/to/archive.zip인식되는 아카이브 ~/.avfs/path/to/archive.zip#인 경우 아카이브의 컨텐츠를 포함하는 것으로 보이는 디렉토리입니다.

find ~/.avfs"$PWD" \( -name '*.7z' -o -name '*.zip' -o -name '*.tar.gz' -o -name '*.tgz' \) \
     -exec sh -c '
                  find "$0#" -name "*vacation*.jpg"
                 ' {} 'Test::Version' \;

설명 :

  • AVFS 파일 시스템을 마운트하십시오.
  • ~/.avfs$PWD에서 현재 아카이브 의 AVFS보기 인 아카이브 파일을 찾으십시오 .
  • 각 아카이브에 대해 지정된 쉘 스 니펫을 실행하십시오 ( $0= 아카이브 이름 및 $1= 패턴으로 검색).
  • $0#아카이브의 디렉토리보기입니다 $0.
  • {\}{}외부 인수가 내부 인수로 find대체 되는 경우가 아니라 필요합니다 (일부는 그렇지 않음).{}-exec ;

또는 zsh ≥4.3에서 :

mountavfs
ls -l ~/.avfs$PWD/**/*.(7z|tgz|tar.gz|zip)(e\''
     reply=($REPLY\#/**/*vacation*.jpg(.N))
'\')

설명 :

  • ~/.avfs$PWD/**/*.(7z|tgz|tar.gz|zip) 현재 디렉토리 및 해당 서브 디렉토리의 AVFS보기에서 아카이브를 일치시킵니다.
  • PATTERN(e\''CODE'\')PATTERN의 각 일치에 CODE를 적용합니다. 일치하는 파일의 이름은입니다 $REPLY. reply배열을 설정하면 일치 항목이 이름 목록으로 바뀝니다.
  • $REPLY\# 아카이브의 디렉토리보기입니다.
  • $REPLY\#/**/*vacation*.jpg*vacation*.jpg아카이브의 파일 과 일치 합니다.
  • N일치가없는 경우 패턴을 만드는 규정 글로브 빈 목록을 확장합니다.

답변

당신이에서 avfs 솔루션이 간단한 무언가를 원하는 경우에, 나는 그것이라고 할 수있는 파이썬 스크립트 작성 arkfind을 . 실제로 할 수 있습니다

$ arkfind /path/to/search/ -g "*vacation*jpg"

이 작업은 재귀 적으로 수행되므로 아카이브 내부의 아카이브를 임의의 깊이로 볼 수 있습니다.


답변

일반적인 해결책 :

find -iname '*.zip' -exec unzip -l {} \; 2>/dev/null | grep '\.zip\|DESIRED_FILE_TO_SEARCH'

예:

find -iname '*.zip' -exec unzip -l {} \; 2>/dev/null | grep '\.zip\|characterize.txt'

레술은 다음과 같습니다.

foozip1.zip:
foozip2.zip:
foozip3.zip:
    DESIRED_FILE_TO_SEARCH
foozip4.zip:
...

히트 파일이있는 zip 파일 만 원하는 경우 :

find -iname '*.zip' -exec unzip -l {} \; 2>/dev/null | grep '\.zip\|FILENAME' | grep -B1 'FILENAME'

여기서 FILENAME 은 (는) 두 번 사용되므로 변수를 사용할 수 있습니다.

찾기로 PATH / TO / SEARCH를 사용할 수 있습니다


답변

작동하는 또 다른 솔루션은 zgrep

zgrep -r filename *.zip

답변

IMHO 사용자 친화도 bash의 것이어야합니다.

 while read -r zip_file ; do echo "$zip_file" ; unzip -l "$zip_file" | \
 grep -i --color=always -R "$to_srch"; \
 done < <(find . \( -name '*.7z' -o -name '*.zip' \)) | \
 less -R

그리고 tar (이것은 테스트되지 않았습니다 …)

 while read -r tar_file ; do echo "$tar_file" ; tar -tf  "$tar_file" | \
 grep -i --color=always -R "$to_srch"; \
 done < <(find . \( -name '*.tar.gz' -o -name '*.tar' \)) | \
 less -R

답변

libarchivebsdtar대부분의 파일 형식을 처리 할 수 ​​있으므로 다음을 수행 할 수 있습니다.

find . \( -name '*.zip' -o     \
          -name '*.tar' -o     \
          -name '*.tar.gz' -o  \
          -name '*.tar.bz2' -o \
          -name '*.tar.xz' -o  \
          -name '*.tgz' -o     \
          -name '*.tbz2' -o    \
          -name '*.7z' -o      \
          -name '*.iso' -o     \
          -name '*.cpio' -o    \
          -name '*.a' -o       \
          -name '*.ar' \)      \
       -type f                 \
       -exec bsdtar tf {} '*vacation*jpg' \; 2> /dev/null

다음과 같이 GNU find를 단순화하고 대소 문자를 구분하지 않고 향상시킬 수 있습니다 .

find . -regextype egrep \
       -iregex '.*\.(zip|7z|iso|cpio|ar?|tar(|\.[gx]z|\.bz2)|tgz|tbz2)' \
       -type f \
       -exec bsdtar tf {} '*vacation*jpg' \; 2> /dev/null

*vacation*jpg그래도 해당 파일이 있는 아카이브의 경로는 인쇄하지 않습니다 . 해당 이름을 인쇄하려면 마지막 줄을 다음과 같이 바꾸십시오.

-exec sh -ac '
   for ARCHIVE do
     bsdtar tf "$ARCHIVE" "*vacation*jpg" |
       awk '\''{print ENVIRON["ARCHIVE"] ": " $0}'\''
   done' sh {} + 2> /dev/null

다음과 같은 출력을 제공합니다.

./a.zip: foo/blah_vacation.jpg
./a.zip: bar/blih_vacation.jpg
./a.tar.gz: foo/blah_vacation.jpg
./a.tar.gz: bar/blih_vacation.jpg

또는과 zsh:

setopt extendedglob # best in ~/.zshrc
for archive (**/*.(#i)(zip|7z|iso|cpio|a|ar|tar(|.gz|.xz|.bz2)|tgz|tbz2)(.ND)) {
  matches=("${(f@)$(bsdtar tf $archive '*vacation*jpg' 2> /dev/null)"})
  (($#matches)) && printf '%s\n' "$archive: "$^matches
}

단지 다른 파일 형식의 숫자가 있습니다 zip또는 tgz같은 변장에있는 파일 .jar또는 .docx파일입니다. 파일을 find/ zsh검색 패턴에 추가 bsdtar하고 확장명을 신경 쓰지 않습니다 (파일 형식을 결정하기 위해 확장명에 의존하지 않는 것처럼).

주의 *vacation*.jpg가에 일치합니다 그래서 위, 전체 아카이브 멤버 경로가 아닌 파일 이름을 일치 vacation.jpg에도하지만 vacation/2014/file.jpg.

파일 이름 만 일치 시키려면 추출 모드 -s를 사용하고 정규식을 p플래그 와 함께 사용 하여 (대체)를 사용 하여 일치하는 파일의 이름을 인쇄 한 다음 파일이 추출되지 않도록하십시오.

bsdtar -'s|.*vacation[^/]*$||' -'s|.*||' -xf "$archive"

stderr에 목록을 출력하고 >>모든 행에 추가 합니다. 어쨌든, bsdtar대부분의 tar구현 과 같이 파일 이름에 줄 바꿈 또는 백 슬래시 ( \n또는로 렌더링 됨 \\) 와 같은 문자가 포함되어 있으면 파일 이름이 표시 될 수 있습니다 .