Compruebe si existe un determinado tipo de archivo / extensión en el directorio

84

¿Cómo haría para saber si los archivos de una extensión específica están presentes en un directorio, con bash?

Algo como

if [ -e *.flac ]; then 
echo true; 
fi 
Wurlitzer
fuente

Respuestas:

104
#!/bin/bash

count=`ls -1 *.flac 2>/dev/null | wc -l`
if [ $count != 0 ]
then 
echo true
fi 
JeremyWeir
fuente
9
Hola Thomas, ¿qué tal si agregas una mejor solución a la pregunta en lugar de solo un voto negativo?
JeremyWeir
8
También Thomas, su ejemplo de por qué no usarlo es usar ls -l, mi respuesta usals -1
JeremyWeir
10
Y esta respuesta no está analizando la salida, solo está contando la salida de líneas, y estoy casi seguro de que incluso si hay caracteres extraños en un nombre de archivo, ls -1se imprimirá una línea por archivo
JeremyWeir
2
El recuento de líneas está analizando. Y devolverá un número incorrecto si algún archivo lo contiene \n(y sí, eso es válido en los nombres de archivo).
marcelm
1
Por favor, díganos entonces, ¿qué carácter mágico tendría que estar en el nombre de un archivo para que la línea no cuente nada?
yeoman
27
#/bin/bash

myarray=(`find ./ -maxdepth 1 -name "*.py"`)
if [ ${#myarray[@]} -gt 0 ]; then 
    echo true 
else 
    echo false
fi
semana
fuente
5
Este es bueno porque puedes hacer algo con los archivos después de encontrarlos.
ephsmith
+1 para envolver la subcapa ejecutando find entre paréntesis para hacer myarray una variable de matriz. De lo contrario, si buscar no devuelve ningún resultado ${#myarray[@]}igual a 1
shaffooo
también podría simplificar usando en ls -1 *.pylugar de buscar
JrBenito
Si alguno de los archivos tiene un espacio en el nombre, esto contará una instancia como dos.
Jon Griffith
16

Esto usa ls (1), si no existen archivos flac, ls informa de un error y se cierra el script; De lo contrario, el script continúa y los archivos pueden ser procesados.

#! /bin/sh
ls *.flac  >/dev/null || exit
## Do something with flac files here
deshilachador
fuente
4
Para un silencio adicional, redirija 2> & 1 también.
Jasper
6
La versión if:if ls *.flac >/dev/null 2>&1; then ... fi;
Josiah Yoder
9
shopt -s nullglob
if [[ -n $(echo *.flac) ]]    # or [ -n "$(echo *.flac)" ]
then 
    echo true
fi
Dennis Williamson
fuente
4

Debe tener cuidado con qué bandera coloca en su ifdeclaración y cómo se relaciona con el resultado que desea.

Si desea verificar solo archivos normales y no otros tipos de entradas del sistema de archivos, entonces querrá cambiar el esqueleto de su código a:

if [ -f file ]; then
echo true;
fi

El uso de la -frestringe ifa archivos normales, mientras que -ees más expansivo y coincidirá con todos los tipos de entradas del sistema de archivos. Por supuesto, hay otras opciones como -ddirectorios, etc. Consulte http://tldp.org/LDP/abs/html/fto.html para obtener una buena lista.

Como lo señaló @msw, test(es decir [) se ahogará si intenta alimentarlo con más de un argumento. Esto podría suceder en su caso si el glob para *.flacdevolvió más de un archivo. En ese caso, intente envolver su ifprueba en un bucle como:

for file in ./*.pdf
do
    if [ -f "${file}" ]; then
    echo 'true';
    break
    fi
done

De esta manera, breaken la primera instancia de la extensión de archivo que desea y puede continuar con el resto del script.

dtlussier
fuente
1
excepto test(también conocido como [) se queja si el patrón se expande a más de un archivo: "operador binario esperado" o "demasiados argumentos"
msw
1
@msw - gracias, ni siquiera pensé en ese tema. Intenté modificar mi respuesta para tenerla en cuenta.
dtlussier
Debe citar la variable, es decir, use "$file", porque el nombre del archivo puede contener algunos caracteres incorrectos, como espacios o asteriscos.
Roman Cheplyaka
3
#!/bin/bash
files=$(ls /home/somedir/*.flac 2> /dev/null | wc -l)
if [ "$files" != "0" ]
then
echo "Some files exists."
else
echo "No files with that extension."
fi
Ruel
fuente
3

La mejor solución (if [ -e *.flac ];)no funcionó para mí, dando:[: too many arguments

if ls *.flac >/dev/null 2>&1; entonces funcionará.

Erik Buitenhuis
fuente
3

Puede usar -f para verificar si existen archivos de un tipo específico:

#!/bin/bash

if [ -f *.flac ] ; then
   echo true
fi 
Uzi
fuente
Esto funciona, pero está enterrando el lede; la razón por la que funciona es porque la abrazadera única [(a diferencia de la más común [[) no evita el globbing.
Adrian Petrescu
2
   shopt -s nullglob
   set -- $(echo *.ext)
    if [ "${#}" -gt 0 ];then
      echo "got file"
    fi
ghostdog74
fuente
Esto está mal. Primero, probablemente quiso decir en -gelugar de -gt, porque de lo contrario su código no detectará el archivo único. En segundo lugar, si no hay archivos que coincidan con el patrón, cualquier shell conforme dejará la cadena *.extintacta, por lo que aún obtendrá un "resultado".
Roman Cheplyaka
$ # es 1 para un archivo único y 0 para ningún archivo.
frayser
1

bash solo:

any_with_ext () ( 
    ext="$1"
    any=false
    shopt -s nullglob
    for f in *."$ext"; do
        any=true
        break
    done
    echo $any 
)

if $( any_with_ext flac ); then
    echo "have some flac"
else 
    echo "dir is flac-free"
fi

Utilizo paréntesis en lugar de llaves para asegurarme de que se usa una subcapa (no quiero golpear su nullglobconfiguración actual ).

Glenn Jackman
fuente
1

Aquí hay una solución que no usa comandos externos (es decir, no ls), sino una función de shell. Probado en bash:

shopt -s nullglob
function have_any() {
    [ $# -gt 0 ]
}

if have_any ./*.flac; then
    echo true
fi

La función have_anyutiliza $#para contar sus argumentos y [ $# -gt 0 ]luego prueba si hay al menos un argumento. El uso de en ./*.flaclugar de solo *.flacen la llamada a have_anyes para evitar problemas causados ​​por archivos con nombres como --help.

jochen
fuente
1

Para completar, con zsh:

if [[ -n *.flac(#qN) ]]; then
  echo true
fi

Esto se enumera al final de la sección Expresiones condicionales en el manual de zsh. Dado que [[deshabilita el globbing de nombre de archivo, necesitamos forzar la generación del nombre de archivo usando (#q)al final de la cadena de globbing, luego la Nbandera ( NULL_GLOBopción) para forzar que la cadena generada esté vacía en caso de que no haya coincidencia.

Yo asi
fuente
1

Aquí tienes una solución bastante simple:

if [ "$(ls -A | grep -i \\.flac\$)" ]; then echo true; fi

Como puede ver, esta es solo una línea de código, pero funciona bastante bien. Debería funcionar tanto con bash como con un shell compatible con posix como dash. Tampoco distingue entre mayúsculas y minúsculas y no le importa qué tipo de archivos (regulares, enlace simbólico, directorio, etc.) estén presentes, lo que podría ser útil si tiene algunos enlaces simbólicos o algo así.

TSJNachos117
fuente
me gusta esto porque ls -AR hace búsqueda recursiva. bueno para buscar el contenido de los archivos zip después de descomprimirlos.
Justin Cress
0

Probé esto:

if [ -f *.html ]; then
    echo "html files exist"
else
    echo "html files dont exist"
fi

Usé este código sin ningún problema para otros archivos, pero para los archivos html recibí un error :

[: too many arguments

Luego probé la solución de conteo de @ JeremyWeir, que funcionó para mí.

Tenga en cuenta que tendrá que restablecer el recuento si está haciendo esto en un bucle:

count=$((0))
GChuf
fuente
0

Esto debería funcionar en cualquier shell similar a borne que existe:

if [ "$(find . -maxdepth 1 -type f | grep -i '.*\.flac$')" ]; then
    echo true
fi

Esto también funciona con GNU find, pero IDK si es compatible con otras implementaciones de find:

if [ "$(find . -maxdepth 1 -type f -iname \*.flac)" ]; then
    echo true
fi
TSJNachos117
fuente