bash - ¿Cómo omitir el bucle for cuando no hay archivos coincidentes?
for-loop wildcard (2)
La forma estándar de hacer esto (si no puede o no quiere usar
nullglob
) es simplemente verificar si el archivo existe.
for file in foo*; do
[ -f "$file" ] || continue
...
done
La sobrecarga de verificar cada valor de
$file
es necesaria porque si
$file
expande a
foo*
, todavía no sabe si realmente
hubo
un archivo llamado
foo*
(porque coincide con el patrón) o si el patrón no pudo coincidir y expandido a sí mismo.
El uso de
nullglob
, por supuesto, elimina esa ambigüedad porque una expansión fallida no produce argumentos y el ciclo en sí nunca ejecuta el cuerpo.
Cuando recorro todos los archivos comenzando por
foo
lo hago
for f in foo* ; do echo "result = $f" ; done
El problema es cuando
ningún archivo
comienza por
foo
me sale:
result = foo*
Lo que significa que el bucle se ejecuta una vez, incluso si ningún archivo comienza por
foo
.
¿Cómo es esto posible? ¿Cómo puedo recorrer todos los archivos (y no recorrerlo si no hay ningún archivo)?
Puede detener este comportamiento estableciendo nullglob :
shopt -s nullglob
Desde la página vinculada:
nullglob
es una opción de shell Bash que modifica la expansión [[glob]] de tal manera que los patrones que no coinciden con ningún archivo se expanden a cero argumentos, en lugar de a sí mismos.
Puede eliminar esta configuración con
-u
(sin establecer, mientras que
s
es para establecer):
shopt -u nullglob
Prueba
$ touch foo1 foo2 foo3
$ for file in foo*; do echo "$file"; done
foo1
foo2
foo3
$ rm foo*
Veamos:
$ for file in foo*; do echo "$file"; done
foo*
Configuración de
nullglob
:
$ shopt -s nullglob
$ for file in foo*; do echo "$file"; done
$
Y luego deshabilitamos el comportamiento:
$ shopt -u nullglob
$ for file in foo*; do echo "$file"; done
foo*