Como procurar texto em arquivos compactados e obter apenas o nome do arquivo

2

Estou tentando encontrar apenas os nomes dos arquivos que contêm uma string específica. Os arquivos são compactados ( .gz ).

Não tenho zgrep instalado e não consigo instalá-lo. Portanto, não posso usar a opção -l .

Eu tentei usar gzip e gunzip com a opção -c e pipping para grep -l , mas isso não funcionou, eu também usei zcat , mas isso também não funcionou. Alguma pista?

(Nota: o SO é o Solaris 10).

    
por Luis 21.10.2015 / 21:02

3 respostas

3

Você pode fazer o trabalho do zgrep manualmente. Como você deseja apenas os nomes dos arquivos, use grep apenas para testar a presença do padrão e imprima o nome do arquivo se o padrão for encontrado.

#!/bin/sh
pattern=$1; shift
PATH='getconf PATH':$PATH # needed on Solaris 10 and earlier
                          # to get a standard grep
export PATH
found=0
for x do
  if case "$x" in
      *.gz|*.[zZ]) <"$x" gzip -dc | grep -q -e "$pattern";;
      *) <"$x" grep -q -e "$pattern";; 
     esac
  then
    found=1
    printf '%s\n' "$x"
  fi
done
if [ $found -eq 0 ]; then exit 1; fi

Para ser executado como:

that-script 'pattern' file1 file2.gz file3.Z file.*.gz ...

Algumas notas específicas para você executando o Solaris 10 (também se aplicam a versões anteriores e, em alguns aspectos, ao Solaris 11 também).

  • nesses sistemas, /bin/sh é um shell Bourne em oposição a um POSIX sh padrão. Você tem a opção de alterar seu she-bang para #! /usr/xpg4/bin/sh - para obter um sh padrão ou restringir-se à antiga sintaxe Bourne como fazemos aqui (portanto, não $(...) , no case $x in (x)... ) ( O Solaris 11 agora está usando um shell compatível com POSIX para seu /bin/sh (ksh93)).
  • nesses sistemas, zcat apenas processa .Z arquivos compactados por compress como eram nos tempos antigos. Você precisa invocar gzip para .gz arquivos.
  • Por padrão, você não precisa necessariamente de utilitários padrão. Por exemplo, o padrão grep in /usr/bin é antigo e não suporta a opção -q padrão. Para obter os utilitários padrão, você precisa atualizar $PATH com os caminhos onde encontrar os utilitários padrão (como saída por getconf PATH ).

Se você quiser exibir o nome do membro do arquivo e o número da linha ou o conteúdo, você precisará obter os dados da linha do grep e o nome do membro do script. Remova a opção -q da invocação de grep e pós-processe seu conteúdo.

#!/bin/ksh
pattern=$1; shift
export PATH="$(getconf PATH):$PATH" # needed on Solaris 10 and earlier
                                    # to get a standard grep
found=0
for x do
  case "$x" in
      *.gz|*.[zZ]) <"$x" gzip -dc | grep -n -e "$pattern";;
      *) <"$x" grep -n -e "$pattern";; 
  esac | {
    filename=$x awk '{print ENVIRON["filename"] ":" $0; found=1}
                     END {exit(!found)}' && found=1
  }
done
if [ $found -eq 0 ]; then exit 1; fi
    
por 21.10.2015 / 22:12
1

Aqui está outra solução:

#!/bin/bash
# Grab the pattern, just like grep
re="$1"; shift

# Loop across the remaining arguments, or stdin if none
test 0 -eq $# && set -- -
for file
do
    # Search through the file (compressed or otherwise)
    zcat -f "$file" | grep -q "$re" && echo "$file"
done

Você deve copiar isso em um arquivo e torná-lo executável ( chmod a+x {filename} e, em seguida, usá-lo de maneira semelhante a zgrep :

mkdir -p ~/bin
export PATH="$HOME/bin:$PATH"  # Add the ~/bin directory to your PATH. Also add this line to your ~/.profile

cat > ~/bin/mygrep             # Paste the file at this point, hit Ctrl/D on a blank line to end. Or otherwise edit ~/bin/mygrep
chmod a+x ~/bin/mygrep         # Make it executable

mygrep 'hello.*world' a*       # Search for the RE 'hello.*world' in all files beginning with 'a'

Se você achar que zcat -f ou grep -q não são reconhecidos, você pode trocar cada um pelo seguinte

( zcat "$file" 2>/dev/null || cat "$file" )    # zcat -f "$file"
grep "$re" 2>/dev/null                         # grep -q "$re"

Com ambas as substituições aplicadas, a linha de substituição resultante seria semelhante a esta

( zcat "$file" 2>/dev/null || cat "$file" ) | grep "$re" 2>/dev/null && echo "$file"
    
por 21.10.2015 / 22:26
0

Como seus arquivos são realmente arquivos tar.gz, você precisa descompactá-los também. Tar é um utilitário de arquivamento que empacota vários arquivos juntos (no seu caso, apenas um) e foi originalmente usado para fazer backup de dados em unidades de fita.

O utilitário tar originalmente não comprimiria o conteúdo, portanto, porque ele geralmente era transmitido através de gzip ou outros utilitários para compressão .. se você descompactar um tar.gz você ainda tem a camada de alcatrão e é por isso que ele não está funcionando.

nos dias de hoje, o tar de pistola vai tar e zip para você em um comando usando o comando "z".

para que você possa fazer o que quiser, eu acho que você precisa usar o extrato de tar "x" descompactar "z" de um arquivo de destino "f" e fluxo para stdout "O", em seguida, pipe para grep. Deve ser algo como isto:

 tar -xzf mycompressedlogfile.tar.gz -O | grep -l "pattern"

Como sua versão do tar não tem -z tente encanar a saída do gzip através do tar antes de seu grep

 gzip -dc mycompressedlogfile.tar.gz | tar -xOf - | grep -l "pattern"

Mas eu não acho que a versão Solaris 10 do tar suporte a opção "O" para transmitir o conteúdo tar para stdout. :( Você provavelmente vai ter que fazer o acima (sem o O assim "tar -xf -") para cada arquivo de dentro de um diretório de trabalho, ou de alguma forma para ter certeza de que você pode contabilizar os arquivos que são criados, procure o conteúdo e, em seguida, exclua o (s) arquivo (s) .Desculpe a menos que você possa instalar o gnu-tar na máquina Solaris.

Eu acho que a partir da resposta selecionada, você foi capaz de pesquisar o fluxo de alcatrão para o padrão (uma vez que não é comprimido, acho que faz sentido) e descobrir de lá .. :) bom negócio.

Que bom que você recebeu sua resposta.

    
por 23.10.2015 / 16:07