Soluzione 1
La soluzione più vicina è da usare find
con -print0
e leggi l'output con while read …
:
find -name "*.log" -o -name "*.err" -o -name "*.out" -type f -print0 | while IFS= read -r -d '' logfile; do
...
Continua a usare "$logfile"
con le virgolette, come dovresti sempre quando usi le variabili.
Soluzione 2
Un'altra soluzione sarebbe quella di non usare find
del tutto e basta grep
eseguire su più file:
shopt -s nullglob
shopt -s globstar
grep "api/" **/*.log **/*.err **/*.out
Qui, globstar
abilita la corrispondenza ricorsiva delle directory con **
. Dovresti impostare nullglob
per evitare errori se una di queste estensioni di file non esiste.
Questo funziona solo per un insieme limitato di file, poiché è possibile raggiungere la lunghezza massima degli argomenti della riga di comando.
Perché l'errore si verifica?
Non dovresti mai correre for
sull'output di find
(o ls
o qualsiasi altra funzione che restituisce nomi di file con spazi bianchi). Leggere Questo articolo per maggiori informazioni sul motivo per cui questo è un problema e cosa può essere fatto per risolverlo.
In breve, Bash divide gli argomenti in spazi vuoti. Immagina di avere tre file, a
, foo bar
e b
, quindi la linea sarebbe valorizzata a:
for logfile in a foo bar b; do
Ovviamente, Bash imposterà logfile
a a
, foo
, bar
, e b
, che non è quello che volevi. Se fosse possibile specificare manualmente l'input for
, dovresti avvolgere questi nomi di file tra virgolette per risolvere il problema.
Per fare ciò automaticamente, la soluzione è di delimitare questi nomi di file con a NUL
personaggio (che è ciò che il -print0
opzione fa) e quindi dividere l'output in base a quello NUL
carattere di nuovo (che è ciò che il -d ''
nel read
lo fa).