Solução 1
A solução mais próxima é usar find
com -print0
e leia a saída com while read …
:
find -name "*.log" -o -name "*.err" -o -name "*.out" -type f -print0 | while IFS= read -r -d '' logfile; do
...
Continue usando "$logfile"
com aspas, como você sempre deve ao usar variáveis.
Solução 2
Outra solução seria não usar find
em tudo e apenas deixe grep
executar em vários arquivos:
shopt -s nullglob
shopt -s globstar
grep "api/" **/*.log **/*.err **/*.out
Aqui, globstar
permite a correspondência recursiva de diretórios com **
. Você deve definir nullglob
para evitar erros se uma dessas extensões de arquivo não existir.
Isso só funciona para um conjunto limitado de arquivos, pois você pode atingir o tamanho máximo dos argumentos da linha de comando.
Por que o erro acontece?
Você nunca deve correr for
na saída de find
(ou ls
, ou qualquer outra função que produza nomes de arquivos com espaço em branco). Ler Este artigo para mais informações sobre por que isso é um problema e o que pode ser feito para resolvê-lo.
Em suma, o Bash divide os argumentos por espaço em branco. Imagine que você tenha três arquivos a
, foo bar
e b
, então a linha seria avaliada para:
for logfile in a foo bar b; do
Obviamente, Bash irá definir logfile
para a
, foo
, bar
e b
, que não é o que você queria. Se você pudesse especificar manualmente a entrada para for
, você envolveria esses nomes de arquivos entre aspas para resolver o problema.
Para fazer isso automaticamente, a solução é delimitar esses nomes de arquivos com um NUL
personagem (que é o que o -print0
opção faz) e, em seguida, dividir a saída com base nesse NUL
personagem novamente (que é o que o -d ''
em read
faz).