기껏해야 다음과 같은 전화를하고 싶습니다 :
$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
답변
libarchive
의 bsdtar
대부분의 파일 형식을 처리 할 수 있으므로 다음을 수행 할 수 있습니다.
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
또는로 렌더링 됨 \\
) 와 같은 문자가 포함되어 있으면 파일 이름이 표시 될 수 있습니다 .