Estoy tratando de escribir un if
declaración para probar si hay archivos que coincidan con un determinado patrón. Si hay un archivo de texto en un directorio, debe ejecutar un script determinado.
Mi código actualmente:
if [ -f /*.txt ]; then ./script fi
Por favor dé algunas ideas; Solo quiero ejecutar el script si hay un .txt
en el directorio.
Respuesta aceptada:
[ -f /*.txt ]
devolvería verdadero solo si hay uno (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í [
).
Entonces, si hay un /a.txt
y /b.txt
, [
se le pasarán 5 argumentos:[
, -f
, /a.txt
, /b.txt
y ]
. [
luego se quejaría de que -f
recibe demasiados argumentos.
Si desea comprobar que el *.txt
el patrón se expande a al menos un archivo no oculto (regular o no), en el bash
concha:
shopt -s nullglob
set -- *.txt
if [ "$#" -gt 0 ]; then
./script "[email protected]" # 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 (shopt
es, nullglob
en realidad proviene de zsh
), pero shells como ksh93
, zsh
, yash
, tcsh
tienen declaraciones equivalentes.
Con zsh
, la prueba para hay archivos que coincidan con un patrón se puede escribir usando una función anónima y el N
(para nullglob
) y Y1
(para detenerse después de la primera búsqueda) calificador global:
if ()(($#)) *.txt(NY1); then
do-something
fi
Tenga en cuenta que esos encuentran 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 a comandos como ls
o stat
en esa lista de archivos calculados por el shell.
El estándar sh
equivalente sería:
set -- [*].txt *.txt
case "$1$2" in
('[*].txt*.txt') ;;
(*) shift; script "[email protected]"
esac
El problema es que con los shells Bourne o POSIX, si un patrón no coincide, se expande a sí mismo. Entonces si *.txt
se expande a *.txt
, no sabes si es porque no hay .txt
archivo en el directorio o porque hay un archivo llamado *.txt
. Usando [*].txt *.txt
permite discriminar entre los dos.
Ahora, si quieres comprobar que el *.txt
coincide con al menos un regular archivo o enlace simbólico a un archivo normal (como su [ -f *.txt ]
sugiere que desea hacer), o que todos los archivos que coincidan con *.txt
son normales archivos (después de la resolución del enlace simbólico), eso es otro asunto.
Con zsh
:
if ()(($#)) *.txt(NY1-.); then
echo "there is at least one regular .txt file"
fi
if ()(($#)) *.txt(NY1^-.); then
echo "there is at least one non-regular .txt files"
fi
(quitar el -
si desea realizar la prueba antes de la resolución del enlace simbólico, es decir, considere los enlaces simbólicos como archivos no regulares, ya sea que apunten a archivos regulares o no).