[ -f /*.txt ]
devolvería verdadero solo si hay un (y solo uno) archivo no oculto en /
cuyo nombre termina en.txt
y si ese archivo es un archivo normal o un enlace simbólico a un archivo normal.
Esto se debe a que el shell expande los comodines antes de pasarlos al comando (aquí [
).
Así que si hay una /a.txt
, y /b.txt
, [
será pasado 5 argumentos: [
, -f
, /a.txt
, /b.txt
y ]
. [
luego se quejaría de que-f
se le dan demasiados argumentos.
Si desea comprobar que el *.txt
patrón se expande al menos a un archivo no oculto (normal o no):
shopt -s nullglob
set -- *.txt
if [ "$#" -gt 0 ]; then
./script "$@" # call script with that list of files.
fi
# Or with bash arrays so you can keep the arguments:
files=( *.txt )
# apply C-style boolean on member count
(( ${#files[@]} )) && ./script "${files[@]}"
shopt -s nullglob
es bash
específico, pero como conchas ksh93
, zsh
, yash
,tcsh
tienen declaraciones equivalentes.
Tenga en cuenta que encuentra esos archivos leyendo el contenido del directorio, no intenta acceder a esos archivos en absoluto, lo que lo hace más eficiente que las soluciones que llaman comandos como ls
o stat
en esa lista de archivos calculados por el shell.
El sh
equivalente estándar sería:
set -- [*].txt *.txt
case "$1$2" in
('[*].txt*.txt') ;;
(*) shift; script "$@"
esac
El problema es que con los shells Bourne o POSIX, si un patrón no coincide, se expande a sí mismo. Entonces, si se *.txt
expande a *.txt
, no sabes si es porque no hay un .txt
archivo en el directorio o porque hay un archivo llamado *.txt
. El uso [*].txt *.txt
permite discriminar entre los dos.
/
? Además, te falta un punto y coma antesfi
.