Estoy tratando de escribir una ifdeclaración para probar si hay algún archivo que coincida con cierto 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 da algunas ideas; Solo quiero ejecutar el script si hay un .txten el directorio.
shell-script
files
wildcards
test
usuario40952
fuente
fuente

/? Además, te falta un punto y coma antesfi.findcomo se explica aquí en stackoverflow .Respuestas:
devolvería verdadero solo si hay un (y solo uno) archivo no oculto en
/cuyo nombre termina en.txty 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.txty].[luego se quejaría de que-fse le dan demasiados argumentos.Si desea comprobar que el
*.txtpatrón se expande al menos a un archivo no oculto (normal o no):shopt -s nullglobesbashespecífico, pero como conchasksh93,zsh,yash,tcshtienen 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
lsostaten esa lista de archivos calculados por el shell.El
shequivalente estándar sería:El problema es que con los shells Bourne o POSIX, si un patrón no coincide, se expande a sí mismo. Entonces, si se
*.txtexpande a*.txt, no sabes si es porque no hay un.txtarchivo en el directorio o porque hay un archivo llamado*.txt. El uso[*].txt *.txtpermite discriminar entre los dos.fuente
[ -f /*.txt ]es bastante rápido en comparación concompgen.[ -f /*.txt ]estaría equivocado, pero en mi prueba en un directorio que contiene3425archivos,94de los cuales son archivos txt no ocultos,compgen -G "*.txt" > /dev/null 2>&1parecen ser tan rápidos comoset -- *.txt; [ "$#" -gt 0 ](20.5 segundos para ambos cuando se repiten 10000 veces en mi caso).Siempre puedes usar
find:Explicación:
find .: busca en el directorio actual-maxdepth 1: no buscar subdirectorios-type f: busca solo archivos regularesname "*.txt": busca archivos que terminan en.txt2>/dev/null: redirige los mensajes de error a/dev/null| grep -q .: grep para cualquier carácter, devolverá falso si no se encuentran caracteres.&& ./script: Ejecutar./scriptsolo si el comando anterior fue exitoso (&&)fuente
findsolo devuelve falso si tiene problemas para buscar archivos, no si no encuentra ningún archivo. Desea canalizar la salidagrep -q .para verificar si encuentra algo.chmod a-x ..Una posible solución es también Bash incorporado
compgen. Ese comando devuelve todas las coincidencias posibles para un patrón global y tiene un código de salida que indica si algún archivo coincide.Encontré esta pregunta mientras buscaba soluciones más rápidas.
fuente
LC_ALL=C compgen -G "*.txt" > /dev/null.Aquí hay un trazador de líneas para hacerlo:
existen archivos
los archivos no existen
Este enfoque hace uso de
||y&&operadores en bash. Estos son los operadores "o" y "y".Entonces, si el comando stat devuelve un
$?igual a 0, entoncesechose llama al primero , si devuelve un 1, entonces el segundoechose llama .devolver resultados de stat
Esta pregunta está ampliamente cubierta en stackoverflow:
fuente
statcuandols -dpuede hacer lo mismo?ls -denumera un directorio? No pareció funcionar cuando intenté enumerar un directorio con archivos,ls -d *.plpor ejemplo.&&byls *.txty funcionará también. Asegúrese de enviar el stdout y stderr a/dev/nulllo sugerido por @slm.ls *.txty no hay archivos presentes en el directorio de este devolverá una$? = 2, que seguirá funcionando con el caso entonces, pero esta fue una de mis razones para elegirstatmásls. Quería un 0 para el éxito y un 1 para el fracaso.ls -des enumerar directorios en lugar de su contenido. Así quels -dsolo hace lolstaten el archivo, tal como lostathace GNU . Lo que los comandos de estado de salida distintos de cero devuelven en caso de falla es específico del sistema, tiene poco sentido hacer suposiciones sobre ellos.Como señala Chazelas, su script fallaría si la expansión de comodines coincide con más de un archivo.
Sin embargo, hay un truco que uso ( aunque no me gusta mucho ) para evitarlo:
¿Cómo funciona?
La expansión de comodines coincidirá con una serie de nombres de archivos, obtenemos el primero si hay alguno, de lo contrario, nulo si no coincide.
fuente
.txtarchivos que son de tipo regular . Prueba por ejemplo despuésmkdir a.txt; mkfifo b.txt; echo regular > c.txt.Simple como:
wc -lcuenta las líneas en el comodín expandido.fuente
lssalida y casi nunca examinarla$?directamente porqueifya lo hace. Además, usarwcpara ver si sucedió algo está igualmente mal dirigido.Me gusta la solución de matriz anterior, pero eso podría ser un desperdicio con una gran cantidad de archivos: el shell usaría una gran cantidad de memoria para construir la matriz, y solo se probaría el primer elemento.
Aquí hay una estructura alternativa que probé ayer:
$ cd /etc; if [[ $(echo * | grep passwd) ]];then echo yes;else echo no;fi yes $ cd /etc; if [[ $(echo * | grep password) ]];then echo yes;else echo no;fi noEl valor de salida del grep parece estar determinando la ruta a través de la estructura de control. Esto también se prueba con expresiones regulares en lugar de patrones de shell. Algunos de mis sistemas tienen el comando "pcregrep" que permite coincidencias de expresiones regulares mucho más sofisticadas.
(Edité esta respuesta para eliminar un "ls" en la sustitución del comando después de leer la crítica anterior por analizarlo).
fuente
si desea usar una cláusula if, evalúe el recuento:
fuente