O problema não é com $file
, é com o seu uso de $(find…)
.
As variáveis regulares e as $(…)
substituições de processo estão sujeitas exatamente ao mesmo tipo de divisão de palavras. Se você colocar $(find…)
aspas duplas, obterá uma única palavra com toda a saída. Caso contrário, ele será dividido em qualquer espaço em branco - não apenas em novas linhas ou em algum outro limite mágico que você provavelmente esperava.
Uma parte importante do exposto acima é que as escapes de barra invertida não são processadas ao expandir a variável. É apenas dividido em espaços e é isso.
(Em outras palavras, citar $file
não ajudou porque nunca teve o valor correto em primeiro lugar!)
Se você deseja processar todos os arquivos recursivamente, suas opções são:
Leia a saída de find
outra maneira:
find … -print | while read -r file; do
echo "Got $file"
done
(Observação: os nomes dos arquivos também podem incluir novas linhas tecnicamente , portanto, você pode se proteger contra isso, por mais raro que seja:
find … -print0 | while read -r -d "" file; do
echo "Got $file"
done
Para pequenas quantidades de arquivos, use os curingas estendidos do bash:
shopt -s globstar
for file in /path/to/foo/**; do
echo "Got $file"
done
Com diretórios grandes, a vantagem find | while read
é que ele é transmitido - seu script processará os resultados à medida que forem chegando. Enquanto isso, os $(find)
curingas e os curingas precisam coletar tudo na memória primeiro e só então retornar os resultados (possivelmente maciços).
Por outro lado, o uso de um pipe afeta todo o while
loop (não apenas o read
comando); portanto, se você deseja executar algo que deseje ler a entrada do teclado, é necessário fornecer manualmente o stdin original, por exemplo vim "$file" < /dev/tty
.