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 globstar
opció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
read
se puede usar de forma segura en combinación find
estableciendo 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 -exec
opció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
find
también puede cd en el directorio de cada archivo antes de ejecutar un comando mediante el uso de en -execdir
lugar de -exec
, y se puede hacer interactivo (solicitar antes de ejecutar el comando para cada archivo) utilizando en -ok
lugar de -exec
(o en -okdir
lugar de -execdir
).
*: Técnicamente, ambos find
y 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.