La iteración recursiva a través de los archivos en un directorio se puede hacer fácilmente mediante:
find . -type f -exec bar {} \;
Sin embargo, lo anterior no funciona para cosas más complejas, donde es necesario realizar muchas ramas condicionales, bucles, etc. Solía usar esto para lo anterior:
while read line; do [...]; done < <(find . -type f)
Sin embargo, parece que esto no funciona para archivos que contienen caracteres oscuros:
$ touch $'a\nb'
$ find . -type f
./a?b
¿Hay alguna alternativa que maneje bien a personajes tan oscuros?
find ... -exec bash -c 'echo filename is in \$0: "$0"' {} \;
Es una mejor manera de hacerlo.read line
aIFS= read -r line
. El único personaje que lo romperá es una nueva línea.-d $'\0'
es preferible.Respuestas:
Otro uso más para la seguridad
find
:(Esto funciona con cualquier POSIX
find
, pero la parte de shell requiere bash. Con * BSD y GNU find, puede usar en-print0
lugar de-exec printf '%s\0' {} +
, será un poco más rápido).Esto hace posible el uso de entrada estándar dentro del bucle y funciona con cualquier ruta.
fuente
do echo "Filename is '$REPLY'"
Hacer esto es tan simple como:
O...
fuente
El enfoque más simple (pero seguro) es usar el bloqueo de shell:
Para hacer que lo anterior se repita en subdirectorios (en bash), puede usar la
globstar
opción; también configuradodotglob
para coincidir con archivos cuyo nombre comienza con.
:Tenga en cuenta que hasta bash 4.2,
**/
repite en enlaces simbólicos a directorios. Desde bash 4.3,**/
solo se repite en directorios, comofind
.Otra solución común es usar
find -print0
conxargs -0
:Tenga en cuenta que el
h:/g
es realmente correcto ya que el nombre del archivo contiene un\r
.fuente
Es un poco difícil hacer tu ciclo de lectura de forma portátil, pero para bash en particular puedes probar algo como esto .
Porción relevante:
Eso indica
find
que imprima su salida delimitada por caracteres NUL (0x00), yread
que busque líneas delimitadas por NUL (-d $'\0'
) sin manejar barras invertidas como escapes para otros caracteres (-r
) y que no se divida ninguna palabra en las líneas (IFS=
). Dado que 0x00 es un byte que no puede aparecer en nombres de archivo o rutas en Unix, esto debería manejar todos sus problemas de nombres de archivo extraños.fuente
-d ''
es equivalente a-d $'\0'
.