Idealmente, no lo haga de esa manera, porque analizar correctamente los nombres de los archivos en un script de shell siempre es difícil (arréglelo para los espacios, aún tendrá problemas con otros caracteres incrustados, en particular, la nueva línea). Esto incluso aparece como la primera entrada en la página BashPitfalls.
Dicho esto, hay una manera de casi hacer lo que quieres:
oIFS=$IFS
IFS=$'\n'
find . -name '*.txt' | while read -r i; do
# use "$i" with whatever you're doing
done
IFS=$oIFS
Recuerde citar también $i
al usarlo, para evitar que otras cosas interpreten los espacios después. También recuerde configurar $IFS
volver después de usarlo, porque no hacerlo causará errores desconcertantes más tarde.
Esto tiene otra advertencia adjunta:lo que sucede dentro del while
loop puede tener lugar en una subcapa, según la capa exacta que esté utilizando, por lo que es posible que la configuración de las variables no persista. El for
la versión en bucle evita eso, pero al precio de eso, incluso si aplica el $IFS
solución para evitar problemas con los espacios, tendrá problemas si el find
devuelve demasiados archivos.
En algún momento, la solución correcta para todo esto es hacerlo en un lenguaje como Perl o Python en lugar de Shell.
Usa find -print0
y canalícelo a xargs -0
, o escribe tu propio pequeño programa en C y canalízalo a tu pequeño programa en C. Esto es lo que -print0
y -0
fueron inventados para.
Los scripts de shell no son la mejor manera de manejar nombres de archivo con espacios:puede hacerlo, pero se vuelve torpe.
Puede configurar el "separador de campo interno" (IFS
) a algo más que espacio para la división del argumento del bucle, por ejemplo,
ORIGIFS=${IFS}
NL='
'
IFS=${NL}
for i in $(find . -name '*.txt'); do
IFS=${ORIGIFS}
#do stuff
done
IFS=${ORIGIFS}
Restablecí IFS
después de su uso en find, sobre todo porque se ve bien, creo. No he visto ningún problema al configurarlo en nueva línea, pero creo que esto es "más limpio".
Otro método, dependiendo de lo que quieras hacer con la salida de find
, es usar directamente -exec
con el find
comando, o use -print0
y canalícelo en xargs -0
. En el primer caso find
se encarga de que el nombre del archivo se escape. En el -print0
caso, find
imprime su salida con un separador nulo y luego xargs
se divide en esto. Dado que ningún nombre de archivo puede contener ese carácter (que yo sepa), esto también es siempre seguro. Esto es principalmente útil en casos simples; y por lo general no es un gran sustituto para un for
completo bucle.