¿Cómo manejar la coincidencia de bash * cuando no hay coincidencias?

6

El siguiente fragmento de bash funciona muy bien cuando en realidad hay *.txt Archivos en el directorio.

for txt in *.txt
do                                               
  echo "loading data from $txt"
done   

Cuando no hay, lo literal *.txt cae en el bucle como $ txt (no es bueno).

¿Cómo cambio este código para que cuando no haya *.txt archivos, el do ... done bloque es omitido?

kfmfe04
fuente
1
if [ "*.txt" != '*.txt' ] ; then do loop here ; fi
ott--
@ ott-- +1 por ofrecer una solución alternativa
kfmfe04
1
@ott: [ "*.txt" != '*.txt' ] siempre es falso: ambas cadenas están entre comillas, por lo que no se comprueba ninguna coincidencia. Si eliminas las comillas de una ... tiene otros problemas.
Gordon Davisson
@GordonDavisson +1 por señalar esto: el shell scripting parece estar lleno de sorpresas ...
kfmfe04
1
@GordonDavisson De hecho, debe hacerse en 2 pasos para que funcione: files=$(echo *.txt) y entonces: if [ "${files}" != '*.txt' ] ; then.
ott--

Respuestas:

9

Parece que Google tuvo la respuesta a esta.

Pon este encantamiento mágico antes de la for declaración:

shopt -s nullglob
kfmfe04
fuente
Tenga en cuenta que esto puede causar efectos secundarios sorprendentes en comandos como "ls * .txt"
noonex
4

La opción nullglob (respuesta de @kfmfe04) es mejor si está utilizando bash (no es un shell de marca X), y no tiene que preocuparse por cambiar / romper cualquier otra cosa. De lo contrario, puedes usar esta opción (un poco más desordenada):

for txt in *.txt
do
  [ -e "$txt" ] || continue
  echo "loading data from $txt"
done

Esto omite silenciosamente los archivos que no existen (principalmente "* .txt" si no hubo coincidencias, pero posiblemente también los archivos que se eliminaron entre cuando for Generé la lista y cuando el bucle llegó a ellos ...)

Gordon Davisson
fuente
Un archivo podría ser eliminado entre -e invocación y posterior procesamiento aún ...
Koterpillar
@Koterpillar Verdadero, pero probando -e reduce la ventana de tiempo donde la eliminación es un problema.
Gordon Davisson