TL; DR: Se você está aqui apenas para obter a resposta mais correta, provavelmente deseja minha preferência pessoal find . -name '*.txt' -exec process {} \;
(veja a parte inferior desta postagem). Se você tiver tempo, leia o restante para ver várias maneiras diferentes e os problemas com a maioria delas.
A resposta completa:
A melhor maneira depende do que você deseja fazer, mas aqui estão algumas opções. Contanto que nenhum arquivo ou pasta na subárvore tenha um espaço em branco em seu nome, você pode simplesmente fazer um loop sobre os arquivos:
for i in $x; do # Not recommended, will break on whitespace
process "$i"
done
Marginalmente melhor, corte a variável temporária x
:
for i in $(find -name \*.txt); do # Not recommended, will break on whitespace
process "$i"
done
É muito melhor glob quando puder. Cofre em espaço em branco, para arquivos no diretório atual:
for i in *.txt; do # Whitespace-safe but not recursive.
process "$i"
done
Ao ativar a globstar
opção, você pode enviar todos os arquivos correspondentes neste diretório e todos os subdiretórios:
# Make sure globstar is enabled
shopt -s globstar
for i in **/*.txt; do # Whitespace-safe and recursive
process "$i"
done
Em alguns casos, por exemplo, se os nomes dos arquivos já estiverem em um arquivo, você pode precisar usar read
:
# IFS= makes sure it doesn't trim leading and trailing whitespace
# -r prevents interpretation of \ escapes.
while IFS= read -r line; do # Whitespace-safe EXCEPT newlines
process "$line"
done < filename
read
pode ser usado com segurança em combinação com a find
configuração apropriada do delimitador:
find . -name '*.txt' -print0 |
while IFS= read -r -d '' line; do
process "$line"
done
Para pesquisas mais complexas, você provavelmente desejará usar find
, com sua -exec
opção ou com -print0 | xargs -0
:
# execute `process` once for each file
find . -name \*.txt -exec process {} \;
# execute `process` once with all the files as arguments*:
find . -name \*.txt -exec process {} +
# using xargs*
find . -name \*.txt -print0 | xargs -0 process
# using xargs with arguments after each filename (implies one run per filename)
find . -name \*.txt -print0 | xargs -0 -I{} process {} argument
find
também pode cd no diretório de cada arquivo antes de executar um comando usando em -execdir
vez de -exec
e pode ser interativo (prompt antes de executar o comando para cada arquivo) usando em -ok
vez de -exec
(ou em -okdir
vez de -execdir
).
*: Tecnicamente, ambos find
e xargs
(por padrão) executarão o comando com o maior número possível de argumentos na linha de comando, quantas vezes forem necessárias para passar por todos os arquivos. Na prática, a menos que você tenha um número muito grande de arquivos, isso não importará e, se você exceder o comprimento, mas precisar de todos na mesma linha de comando, o SOL encontrará uma maneira diferente.