Busque recursivamente archivos con una extensión específica
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 $extension
en lugar de'in'
)
¿Qué está pasando aquí y dónde está el error? Pero esta llave.
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 $extension
vacías.
find {directory} -type f -name '*.extension'
Ejemplo: para buscar todos csv
los archivos en el directorio actual y sus subdirectorios, use:
find . -type f -name '*.csv'
La sintaxis que uso es un poco diferente a la que sugirió Mat :
find $directory -type f -name \*.in
(es una pulsación menos).
Aunque el uso find
de comandos puede resultar útil aquí, el propio shell proporciona opciones para cumplir este requisito sin herramientas de terceros. El bash
shell 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 extglob
la que debe configurarse usando la shopt
opción que se muestra a continuación. Las opciones se habilitan con el -s
soporte y se deshabilitan con la -u
bandera. Además, podría utilizar un par de opciones más, es decir, nullglob
en las que un globo sin igual se elimina por completo y se reemplaza con un conjunto de cero palabras. Y globstar
eso 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 *.csv
archivos en las rutas recursivas
fileList=(**/*.csv)
La opción **
es recurrir a las subcarpetas y *.csv
es 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 ls
con 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 find
un comando). Por ejemplo, considere un caso en el que necesita obtener todos los archivos de imágenes recursivos *.gif
, es decir, las extensiones, *.png
y *.jpg
todo 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 bash
shells, esta opción no sería correcta.