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).