for i in $(ls);do
    if [ $i = '*.java' ];then
        echo "I do something with the file $i"
    fi
done

Quiero recorrer cada archivo en la carpeta actual y comprobar si coincide con una extensión específica. El código anterior no funciona, ¿sabes por qué?

  • ¿Qué acerca de for i in $(ls *.java); do echo "do something with file $i"; done?
  • ¿por qué no utilizar a encontrar?
  • no hay manera de arreglar eso, si el estado de cuenta?
  • Usted está comparando $i a la cadena literal «*.java»; patrón de expansión no se realiza aquí.
  • Para corregir la declaración si ya la tienes, uso if [[ $i == *.java ]]; then .. (nota el doble [[]]s y no cotizadas *.java).
  • no analizar ls — aceptar @chepner la respuesta
  • Sí, pero este no falla sólo debido a la mala nombres de archivo. Véase mi respuesta a continuación.

InformationsquelleAutor AR89 | 2013-01-24

6 Comentarios

  1. 175

    No apetece trucos necesarios:

    for i in *.java; do
        [ -f "$i" ] || break
        ...
    done

    La guardia asegura que si no hay coincidencia de archivos, el bucle se va a salir sin intentar procesar un archivo que no existe nombre *.java. En bash (o conchas de apoyo algo similar), puede utilizar el nullglob opción
    simplemente ignorar un error de coincidencia y no entrar en el cuerpo del bucle.

    shopt -s nullglob
    for i in *.java; do
        ...
    done
    • Cómo cambiar esto para poder recorrer todos *.java y *.archivos cpp?
    • La forma más sencilla es añadir otro patrón: for i in *.java *.cpp; do. Si ha ampliado los patrones habilitado en bash con shopt -s extglob, puede escribir for i in *[email protected](java|cpp); do.
    • Que si es realmente coincide con alguno de los archivos. Usted necesidad de utilizar shopt -s nullglob de modo que una no-coincidencia de patrón se expande a una secuencia vacía, en lugar de ser tratados literalmente.
    • ¿Este bucle a través de *.java archivos en el directorio actual?
    • sí que debería, tan largo como el actual directorio donde se ejecuta el script de. Si usted no está en el directorio en el que desea ser, sin embargo, usted debe cd a ese directorio antes de iniciar el for bucle
    • Creo que esto no funciona si no hay *.archivos de java presente, se trata como una cadena
    • Depende de tu shell opciones. De forma predeterminada, una no-coincidencia de patrón es tratado como una cadena literal. Puede establecer nullglob tratarla como una secuencia vacía, o conjunto de failglob tratarlo como un error. (Si se establece tanto, failglob tiene prioridad.)
    • Podría ser de utilidad para los no expertos para tener esta indicado en la respuesta como alguien puede copiar pegar y no de trabajo. Un ejemplo perfecto sería alguien que es la conversión de todos «.jpg» archivos «.png» antes de llevar a cabo una función crucial
    • En lugar de [ -f "$i" ] || break, necesitamos [ -f "$i" ] || continue, ¿verdad?
    • Supongo que break y continue tendría el mismo efecto con un solo patrón que no coincide. Con varios patrones (for i in *.java *.foo *.bar, por ejemplo), se desea continue para pasar a la siguiente patrón.
    • es correcto, continue es necesario. Si hay un archivo sin nombre b.java y un directorio llamado a.java, el bucle puede ser terminado por break antes de que llegue b.java.

  2. 13

    la respuesta correcta es @chepner del

    EXT=java
    for i in *.${EXT}; do
        ...
    done

    sin embargo, he aquí un pequeño truco para comprobar si un nombre de archivo de una de las extensiones:

    EXT=java
    for i in *; do
        if [ "${i}" != "${i%.${EXT}}" ];then
            echo "I do something with the file $i"
        fi
    done
    • ¿cómo sería con una variable ext en lugar de .java?
    • he actualizado los ejemplos a utilizar EXT
  3. 10

    De forma recursiva agregar subcarpetas,

    for i in `find . -name "*.java" -type f`; do
        echo "$i"
    done
    • en lugar de find . -name "*.java" -type f -exec echo \{\} \; para evitar misparsing de la salida de find
    • Y si no, al menos deberías citar "$i" dentro del bucle.
    • Esto no funcionará si alguno de los archivos que tienen los espacios en blanco en su nombre.
  4. 4

    Bucle a través de todos los archivos que terminan con: .img, .bin, .txt sufijo, y la impresión del nombre de archivo:

    for i in *.img *.bin *.txt;
    do
      echo "$i"
    done

    O en una manera recursiva (encontrar también en todos los subdirectorios):

    for i in `find . -type f -name "*.img" -o -name "*.bin" -o -name "*.txt"`;
    do
      echo "$i"
    done
  5. 2

    como @chepner dice en su comentario que usted está comparando $i a una cadena fija.

    Para ampliar y rectificar la situación debe utilizar [[ ]] con la expresión regular operador =~

    por ejemplo:

    for i in $(ls);do
        if [[ $i =~ .*\.java$ ]];then
            echo "I want to do something with the file $i"
        fi
    done

    la expresión a la derecha del =~ es probado contra el valor de la mano izquierda del operador y no debe ser citado, ( citado no de error, pero comparar una cadena fija y lo más probable es que no»

    pero @chepner ‘s respuesta anterior utilizando el golf es un mecanismo mucho más eficiente.

  6. 2

    Estoy de acuerdo con las otras respuestas con respecto a la forma correcta de bucle a través de los archivos. Sin embargo, el OP preguntó:

    El código anterior no funciona, ¿sabes por qué?

    Sí!

    Un excelente artículo ¿Cuál es la diferencia entre la prueba, [ y [[ ?] explica en detalle en el que entre otras diferencias, no se puede utilizar expression matching o pattern matching dentro de la test comando (que es la abreviatura de [ )

     
    Nueva característica de la prueba de [[ antiguo de la prueba [ Ejemplo 
    
    La coincidencia de patrón = (o ==) (no disponible) [[ $nombre = a* ]] || echo "el nombre no comienza con 'a': $nombre" 
    
    Expresión Regular =~ (no disponible) [[ $(date) =~ ^Vie\ ...\ 13 ]] && echo "Es viernes 13!" 
    la coincidencia de 
    

    Así que esta es la razón por la que su script falla. Si el OP está interesado en una respuesta con la [[ sintaxis (que tiene la desventaja de no ser admitidos en tantas plataformas como la [ comando), yo sería feliz para editar mi respuesta a incluir.

    EDIT: Cualquier protips de cómo dar formato a los datos en la respuesta como una tabla sería útil!

Dejar respuesta

Please enter your comment!
Please enter your name here