Como grep recursivamente através de arquivos compactados?
16
Estou tentando descobrir quais módulos use Test::Versionno cpan. Então, eu costumava minicpanespelhar isso. Meu problema é que eu preciso percorrer os arquivos baixados e grep os arquivos que estão nos arquivos. Alguém pode me dizer como eu poderia fazer isso? de preferência de uma maneira que me diga qual arquivo no arquivo e em que linha está.
(nota: eles não são todos tarballs, alguns são arquivos zip)
Ok, vamos aplicar a filosofia unix. Quais são os componentes desta tarefa?
Pesquisa de texto: você precisa de uma ferramenta para pesquisar texto em um arquivo, como grep.
Recursiva: você precisa de uma ferramenta para procurar arquivos em uma árvore de diretórios, como find.
Arquivos: você precisa de uma ferramenta para lê-los.
A maioria dos programas unix opera em arquivos. Portanto, para operar facilmente em componentes de arquivamento, você precisa acessá-los como arquivos, ou seja, é necessário acessá-los como diretórios.
O sistema de arquivos AVFS apresenta uma visão do sistema de arquivos em que cada arquivo /path/to/foo.zipestá acessível como um diretório ~/.avfs/path/to/foo/zip#. O AVFS fornece acesso somente leitura aos formatos de arquivo mais comuns.
~/.avfs$PWD/**/*.(tgz|tar.gz|zip) corresponde aos arquivos na visualização AVFS do diretório atual e de seus subdiretórios.
PATTERN(e\''CODE'\')aplica CODE a cada correspondência de PATTERN. O nome do arquivo correspondente está em $REPLY. Definir a replymatriz transforma a correspondência em uma lista de nomes.
$REPLY\# é a visualização do diretório do arquivo morto.
$REPLY\#/**/*.pmcorresponde aos .pmarquivos no arquivo morto.
O Nqualificador glob faz com que o padrão se expanda para uma lista vazia se não houver correspondência.
isso cria outro problema intesting de ter que montar e desmontar tudo, em seguida, dos arquivos, como parte do problema é que existem 22k arquivos que precisam ser pesquisados por meio
xenoterracide
@xenoterracide: Como isso é um problema? Com o AVFS, você tem um único ponto de montagem ( ~/.avfs) e o acesso a cada arquivo ~/.avfs/path/to/archive.zip\#morto é automático ( é um diretório comum no sistema de arquivos AVFS, não um ponto de montagem). Claro, cada arquivo acessado significa um pequeno impacto no desempenho, mas isso é intrínseco ao problema.
Gilles 'SO- stop be evil'
@gilles apenas o fato de que agora eu tenho que passar e descobrir como montá-los primeiro, o que parece um pouco de uma má ideia, melhor montá-los quando for desmontar depois de ser pesquisado.
xenoterracide
@xenoterracide: Novamente: não, você não precisa montá-los individualmente. O fluxo de trabalho completo (além da instalação do AVFS, se necessário) está nos meus trechos de código.
Gilles 'SO- stop be evil'
@gilles bem eu vou ter que cavar para isso um pouco ... porque eu get find: missing argument to -exec'` e lotes deste de zshzsh: Input/output error: Data-Maker-0.27
xenoterracide
0
Parece que eu posso fazer assim
find authors/ -type f -exec zgrep "Test::Version" '{}' +
#!/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
Acabei de ver seu requisito de número de linha. Provavelmente isso pode funcionar com alguma combinação de grep -n e awk para capturar o número da linha. Não pode ser tão simples quanto grep -H para listar o nome do arquivo, pois ele é sempre stdin; portanto, pode exigir mais linhas.
Kyle Smith #
erros quando executado no meu sistema, infinito repetido:tar (child): conform.tar.gz: Cannot open: No such file or directory tar (child): Error is not recoverable: exiting now tar: Child returned status 2 tar: Error is not recoverable: exiting now
xenoterracide 25/05
Também não percebi, quando publiquei isso pela primeira vez, que alguns arquivos no cpan são arquivos zip.
Xenoterracide 25/05
Hum, eu testei com uma estrutura de apenas arquivos .tar.gz - poderia ser mais robusto executar ações apropriadas com base no tipo de arquivo, mas isso deve dar um ponto de partida decente.
Kyle Smith
0
Talvez minha resposta seja útil para alguém:
#!/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
Após a instalação, p7zip-*você é capaz de fazer isso:
ls | xargs -I {} 7z l {} | grep whatever | less
Você não precisa usar lsantes do primeiro canal, qualquer que seja a lista dos arquivos compactados. A final lessmostrará apenas o CAMINHO da vida útil do listet dentro do arquivo compactado, mas não o nome disso.
~/.avfs
) e o acesso a cada arquivo~/.avfs/path/to/archive.zip\#
morto é automático ( é um diretório comum no sistema de arquivos AVFS, não um ponto de montagem). Claro, cada arquivo acessado significa um pequeno impacto no desempenho, mas isso é intrínseco ao problema.find: missing argument to
-exec'` e lotes deste de zshzsh: Input/output error: Data-Maker-0.27
Parece que eu posso fazer assim
No entanto, isso fornece resultados como:
o que não é muito específico para onde no tarball. Espero que alguém possa ter uma resposta melhor.
fonte
Obrigado pelo desafio, eu vim com:
fonte
tar (child): conform.tar.gz: Cannot open: No such file or directory tar (child): Error is not recoverable: exiting now tar: Child returned status 2 tar: Error is not recoverable: exiting now
Talvez minha resposta seja útil para alguém:
fonte
Após a instalação,
p7zip-*
você é capaz de fazer isso:Você não precisa usar
ls
antes do primeiro canal, qualquer que seja a lista dos arquivos compactados. A finalless
mostrará apenas o CAMINHO da vida útil do listet dentro do arquivo compactado, mas não o nome disso.fonte
Use find para localizar todos os arquivos necessários e o zgrep para procurar arquivos compactados:
Não testou isso em tarballs
fonte