list=/errors_exception.txt
cd /test
while IFS= read -r pattern ; do
for file in * ; do
if zcat < "$file" | grep -Fxq "$pattern"; then
echo "$pattern found pattern in $file"
fi
done
done <"$list" > output
Notas:
-
Nenhuma das duas linhas abaixo fará o que você espera:
for PATTERN in 'cat $LIST' for FILE in $(ls)
Em ambos os casos, o shell faz a divisão de palavras que você não deseja. O código sugerido acima evita isso.
-
O arquivo
errors_exception.txt
está realmente no diretório raiz? -
Eu converti as variáveis para minúsculas. Essa é a convenção para variáveis criadas pelo usuário. Esta convenção impedirá que você sobrescreva acidentalmente alguns parâmetros críticos do shell.
Mais sobre a divisão de palavras
Quando o shell é executado:
for PATTERN in 'cat $LIST'
ele executa cat $LIST
. Quando isso acontece, espaços, tabulações e retornos de carro são tratados como a mesma coisa: uma quebra de palavra. Então, efetivamente, após a divisão da palavra, essa linha se torna:
for PATTERN in one one two three four five six
e, conforme o loop for
é executado, PATTERN
é atribuído sequencialmente a um, um, dois, três, quatro, cinco e seis.
O que você realmente quer é que cada linha seja tratada como uma linha. É por isso que a construção while read.... done<"$list"
é usada: em cada loop, lê-se uma linha inteira.
O mesmo problema aconteceria com esta linha se qualquer nome de arquivo tiver espaços:
for FILE in $(ls)
Os resultados de ls
são substituídos na linha e, se houver nomes de arquivos com espaços, tabulações ou retornos de carro neles (todos esses são caracteres legais), os nomes serão divididos em partes. Por exemplo, em um diretório vazio, crie um arquivo:
$ touch "a b c"
Agora, execute um loop for
:
$ for file in $(ls); do echo $file; done
a
b
c
O for
loops é executado três vezes, embora haja apenas um arquivo. Isso ocorre porque o nome do arquivo tem espaços e, após a divisão de palavras, o for
loop obtém três argumentos: a, b e c.
Isso é facilmente evitado. Use em vez disso:
for file in *
O shell é inteligente o suficiente para manter cada nome de arquivo aqui intacto, independentemente de quais caracteres estão em seu nome.
Pesquisa recursiva
Se também quisermos procurar subdiretórios para arquivos gzipados, então podemos usar o recurso globstar do bash da seguinte forma:
list=/errors_exception.txt
cd /test
shopt -s globstar
while IFS= read -r pattern ; do
for file in **/*.gz ; do
if zcat < "$file" | grep -Fxq "$pattern"; then
echo "$pattern found pattern in $file"
fi
done
done <"$list" > output
Isso requer bash
.