use Test::Version
cpan의 어떤 모듈을 찾으려고합니다 . 그래서 나는 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에서 이것을 테스트하지 않았습니다.