Pensé que esto sería simple, pero está resultando más complejo de lo que esperaba.
Quiero iterar a través de todos los archivos de un tipo particular en un directorio, así que escribo esto:
#!/bin/bash
for fname in *.zip ; do
echo current file is ${fname}
done
Esto funciona siempre que haya al menos un archivo coincidente en el directorio. Sin embargo, si no hay archivos coincidentes, obtengo esto:
current file is *.zip
Entonces intenté:
#!/bin/bash
FILES=`ls *.zip`
for fname in "${FILES}" ; do
echo current file is ${fname}
done
Si bien el cuerpo del bucle no se ejecuta cuando no hay archivos, recibo un error de ls:
ls: *.zip: No such file or directory
¿Cómo escribo un bucle que no maneja limpiamente los archivos coincidentes?
shopt -s nullglob
antes de ejecutar el bucle for.FILES=
ls * .zip; for fname in "${FILES}"...
pero funciona como se esperaba confor fname in *.zip ; do....
for file in *.zip
, no`ls ...`
. La sugerencia de @ cuonglm es que se*.zip
expanda a nada cuando el patrón no coincide con ningún archivo.ls
sin argumentos enumera el directorio actual.ls
generalmente se debe evitar analizar la salida de : ¿Por qué no analizarls
? ; También vea el enlace cerca de la parte superior de esa página al artículo ParsingLs de BashGuide .Respuestas:
En
bash
, puede configurar lanullglob
opción para que un patrón que no coincide con nada "desaparezca", en lugar de ser tratado como una cadena literal:En el script de shell POSIX, solo verifica que
fname
existe (y al mismo tiempo[ -f ]
, verifica que sea un archivo normal (o enlace simbólico a un archivo normal) y no otros tipos como directorio / fifo / dispositivo ...):Reemplace
[ -f "$fname" ]
con[ -e "$fname" ] || [ -L "$fname ]
si desea recorrer todos los archivos (no ocultos) cuyo nombre termina.zip
independientemente de su tipo.Reemplace
*.zip
con.*.zip .zip *.zip
si también desea considerar archivos ocultos cuyo nombre termina en.zip
.fuente
shopt -s nullglob
No funcionó para mí en Ubuntu 17.04, pero[ -f "$fname" ] || continue
funcionó bien.bash
.En un comentario aquí mencionas invocar una función ...
fuente
Use buscar
DEBE exportar su función de shell
export -f
para que esto funcione. Ahorafind
ejecuta lobash
que ejecuta su función de shell, y permanece solo en el nivel de directorio actual.fuente
En lugar de:
Tratar:
De esta manera, si ls falla (lo que hace en su caso), grep la salida fallida y regresará como una variable en blanco.
Puede agregar algo de lógica a esto para que devuelva "No se encontró ningún archivo"
De esta forma, si el comando anterior tuvo éxito (salió con un valor 0), imprimirá el archivo actual, de lo contrario, imprimirá "No se encontraron archivos"
fuente
grep
) en lugar de tratar de solucionar el problema utilizando una herramienta mejor (find
) o cambiando la configuración relevante para la solución actual (conshopt -s nullglob
)shopt -s nullglob
, no funciona. Intentéfind
mientras verificaba mi respuesta y seguía fallando. Creo que por lo de exportación dijo Dani.