Unix 'grep' para uma string dentro de todos os arquivos gzip em todos os subdiretórios

8

Como eu faço grep para uma string recursivamente através de todos os .gzarquivos em todos os diretórios e subdiretórios?

Peter Mortensen
fonte

Respostas:

13

@Steve Weet está quase lá. O uso de / dev / null como argumento adicional é uma boa maneira de forçar a exibição do nome do arquivo (lembre-se disso, obrigado Steve), mas ele ainda executa o exec para cada arquivo encontrado - uma sobrecarga enorme.

Você deseja executar o zgrep quantas vezes puder, obtendo o máximo de cada execução:

find . -iname '*.gz' -print0 | xargs -0 zgrep PATTERN

xargsfornecerá o máximo de args (nomes de arquivos) ao zgrep e executará repetidamente até que tenha usado todos os arquivos fornecidos pelo findcomando. O uso das opções -print0e -0permite que funcione se houver espaços em qualquer um dos nomes de arquivos ou diretórios.

No Mac OS X, você pode obter o mesmo efeito sem xargs:

find . -iname '*.gz' -exec zgrep PATTERN {} +
Stephen P
fonte
1 Isso é muito legal. Eu não tinha percebido que os xargs passaram mais de um argumento. Grande parte da minha linha de comando * nix-fu tem 20 anos e eu não acho que o xargs tenha feito isso há 20 anos.
Steve Weet
Acontece que encontrar em os / x se comporta da mesma maneira que xargs
Steve Weet
1
Veja o meu comentário à resposta de Steve Weet sobre o '+' terminando em -exec.
Daniel Andersson
Use -Hpara mostrar sempre o nome do arquivo com a linha correspondente, no GNU grep, pelo menos.
Daniel Andersson
1
$ zgrep --help
Usage: /bin/zgrep [OPTION]... [-e] PATTERN [FILE]...
Look for instances of PATTERN in the input FILEs, using their
uncompressed contents if they are compressed.

Então, algo como

find . -iname "*.gz" -exec zgrep PATTERN {} \
aioobe
fonte
O -exec gerará uma nova instância do zgrep para cada arquivo iterado, evitando que você veja o nome do arquivo. Seria melhor usar zgrep -rpara passar por uma árvore ou se o -r não funcionar, canalizar a saída da descobertaxargs zgrep
Noufal Ibrahim
Eu entro /bin/zgrep: -r: option not supportedno meu sistema Ubuntu recém-instalado.
aioobe
Você pode usar em xargsvez disso.
Noufal Ibrahim
Veja o meu comentário à resposta de Steve Weet sobre o '+' terminando em -exec.
Daniel Andersson
1

@aioobe está quase lá. O comando fará o trabalho mas não lhe dirá o nome do arquivo

O seguinte deve informar o nome do arquivo também:

find . -iname "*.gz" -exec zgrep PATTERN {} /dev/null \;

A adição de /dev/nullirá garantir que zgrep veja dois nomes de arquivos para que ele mostre o nome do arquivo se ele encontrar a string

EDITAR

Pesquisas posteriores revelam que, para minha máquina (OS / X), o -execargumento a ser encontrado adicionará tantos nomes de arquivo quanto possível (semelhante à maneira como xargsse comporta).

Steve Weet
fonte
Isso é muito legal, eu não sabia disso sobre o OSX -exec- eu sou todo sobre portabilidade, então eu não usaria isso em um script, mas ótimo para o prompt de comando.
Para outras versões do find, usando '+' em vez de '\;' finalizar a instrução exec fará o mesmo que o OSX, pelas histórias deste tópico, faz por padrão. Veja a entrada manual para '-exec command {} +'. Não é verdade de todas as versões find, mas da maioria das modernas (por exemplo, em distros baseadas no Debian).
Daniel Andersson
Use -Hpara sempre mostrar o nome do arquivo com a linha correspondente, no GNU grep pelo menos, em vez do /dev/nullhack.
Daniel Andersson
0

O seguinte trabalha um deleite em zsh

for archive in **/*.gz; do
    echo "[${archive}] "
    gzip -dc ${archive} | grep -n "String"
done

Ele também pode trabalhar em bash, ksh, etc ...

Johnsyweb
fonte