TL; DR: Si solo está aquí para obtener la respuesta más correcta, probablemente quiera mi preferencia personal find . -name '*.txt' -exec process {} \;(consulte la parte inferior de esta publicación). Si tiene tiempo, lea el resto para ver varias formas diferentes y los problemas con la mayoría de ellas.
La respuesta completa:
La mejor manera depende de lo que quieras hacer, pero aquí hay algunas opciones. Siempre que ningún archivo o carpeta en el subárbol tenga un espacio en blanco en su nombre, simplemente puede recorrer los archivos:
for i in $x; do # Not recommended, will break on whitespace
process "$i"
done
Marginalmente mejor, recorte la variable temporal x:
for i in $(find -name \*.txt); do # Not recommended, will break on whitespace
process "$i"
done
Es mucho mejor pegarse cuando puedas. Espacio en blanco seguro, para archivos en el directorio actual:
for i in *.txt; do # Whitespace-safe but not recursive.
process "$i"
done
Al habilitar la globstaropción, puede glob todos los archivos coincidentes en este directorio y todos los subdirectorios:
# Make sure globstar is enabled
shopt -s globstar
for i in **/*.txt; do # Whitespace-safe and recursive
process "$i"
done
En algunos casos, por ejemplo, si los nombres de archivo ya están en un archivo, es posible que deba 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
readse puede usar de forma segura en combinación findestableciendo el delimitador adecuadamente:
find . -name '*.txt' -print0 |
while IFS= read -r -d '' line; do
process "$line"
done
Para búsquedas más complejas, es probable que desee utilizar find, ya sea con su -execopción o con -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
findtambién puede cd en el directorio de cada archivo antes de ejecutar un comando mediante el uso de en -execdirlugar de -exec, y se puede hacer interactivo (solicitar antes de ejecutar el comando para cada archivo) utilizando en -oklugar de -exec(o en -okdirlugar de -execdir).
*: Técnicamente, ambos findy xargs(por defecto) ejecutarán el comando con tantos argumentos como puedan caber en la línea de comando, tantas veces como sea necesario para pasar por todos los archivos. En la práctica, a menos que tenga una gran cantidad de archivos, no importará, y si excede la longitud pero los necesita todos en la misma línea de comando, SOL encontrará una forma diferente.