Busque recursivamente archivos con una extensión específica

Resuelto flip asked hace 13 años • 0 respuestas

Estoy intentando encontrar todos los archivos con una extensión específica en un directorio y sus subdirectorios con mi Bash ( Ubuntu 10.04) . LTS (Lucid Lynx)).

Esto es lo que está escrito en un archivo de script:

#!/bin/bash

directory="/home/flip/Desktop"
suffix="in"

browsefolders ()
  for i in "$1"/*;
  do
    echo "dir :$directory"
    echo "filename: $i"
    #    echo ${i#*.}
    extension=`echo "$i" | cut -d'.' -f2`
    echo "Erweiterung $extension"
    if     [ -f "$i" ]; then

        if [ $extension == $suffix ]; then
            echo "$i ends with $in"

        else
            echo "$i does NOT end with $in"
        fi
    elif [ -d "$i" ]; then
    browsefolders "$i"
    fi
  done
}
browsefolders  "$directory"

Desafortunadamente, cuando inicio este script en una terminal, dice:

[: 29: in: unexpected operator

(con $extensionen lugar de'in' )

¿Qué está pasando aquí y dónde está el error? Pero esta llave.

flip avatar May 08 '11 19:05 flip
Aceptado
find "$directory" -type f -name "*.in"

es un poco más corto que todo eso (y más seguro. Se ocupa de los espacios en blanco en los nombres de archivos y directorios).

Es probable que su secuencia de comandos falle en las entradas que no tienen un .nombre en su nombre, lo que las deja $extensionvacías.

Mat avatar May 08 '2011 12:05 Mat
find {directory} -type f -name '*.extension'

Ejemplo: para buscar todos csvlos archivos en el directorio actual y sus subdirectorios, use:

find . -type f -name '*.csv'
Mohammad AlQanneh avatar Aug 23 '2014 17:08 Mohammad AlQanneh

La sintaxis que uso es un poco diferente a la que sugirió Mat :

find $directory -type f -name \*.in

(es una pulsación menos).

Scott C Wilson avatar May 08 '2011 13:05 Scott C Wilson

Aunque el uso findde comandos puede resultar útil aquí, el propio shell proporciona opciones para cumplir este requisito sin herramientas de terceros. El bashshell proporciona una opción de soporte global extendido mediante la cual puede obtener los nombres de los archivos en rutas recursivas que coincidan con las extensiones que desee.

La opción extendida es extglobla que debe configurarse usando la shoptopción que se muestra a continuación. Las opciones se habilitan con el -ssoporte y se deshabilitan con la -ubandera. Además, podría utilizar un par de opciones más, es decir, nullgloben las que un globo sin igual se elimina por completo y se reemplaza con un conjunto de cero palabras. Y globstareso permite recurrir a todos los directorios.

shopt -s extglob nullglob globstar

Ahora todo lo que necesita hacer es formar la expresión global para incluir los archivos de una determinada extensión, lo cual puede hacer como se muestra a continuación. Usamos una matriz para completar los resultados globales porque, cuando se citan correctamente y se expanden, los nombres de archivos con caracteres especiales permanecerán intactos y no se romperán debido a la división de palabras por parte del shell.

Por ejemplo, para enumerar todos los *.csvarchivos en las rutas recursivas

fileList=(**/*.csv)

La opción **es recurrir a las subcarpetas y *.csves una expansión global para incluir cualquier archivo de las extensiones mencionadas. Ahora, para imprimir los archivos reales, simplemente haga

printf '%s\n' "${fileList[@]}"

Usar una matriz y hacer una expansión entre comillas adecuada es la forma correcta cuando se usa en scripts de shell, pero para uso interactivo, simplemente puede usar lscon la expresión global como

ls -1 -- **/*.csv

Esto muy bien podría ampliarse para que coincida con varios archivos, es decir, archivos que terminan con varias extensiones (es decir, similar a agregar varias banderas en findun comando). Por ejemplo, considere un caso en el que necesita obtener todos los archivos de imágenes recursivos *.gif, es decir, las extensiones, *.pngy *.jpgtodo lo que necesita es

ls -1 -- **/+(*.jpg|*.gif|*.png)

Esto muy bien podría ampliarse para tener también resultados negativos. Con la misma sintaxis, se podrían utilizar los resultados del glob para excluir archivos de cierto tipo. Supongamos que desea excluir nombres de archivos con las extensiones anteriores, podría hacerlo

excludeResults=()
excludeResults=(**/!(*.jpg|*.gif|*.png))
printf '%s\n' "${excludeResults[@]}"

La construcción !()es una operación de negación para no incluir ninguna de las extensiones de archivo enumeradas en su interior y |es un operador de alternancia tal como se usa en la biblioteca de Expresiones Regulares Extendidas para hacer una coincidencia OR de los globos.

Tenga en cuenta que este soporte global extendido no está disponible en el shell POSIX bourne y es puramente específico para versiones recientes de bash. Entonces, si está considerando la portabilidad de los scripts que se ejecutan en POSIX y bashshells, esta opción no sería correcta.

Inian avatar Aug 05 '2018 14:08 Inian