gestion - importar clases en python
¿Cómo puedo buscar subcarpetas usando el módulo glob.glob en Python? (9)
Aquí hay una versión adaptada que habilita la funcionalidad glob2
sin usar glob2
.
def find_files(directory, pattern=''*''):
if not os.path.exists(directory):
raise ValueError("Directory not found {}".format(directory))
matches = []
for root, dirnames, filenames in os.walk(directory):
for filename in filenames:
full_path = os.path.join(root, filename)
if fnmatch.filter([full_path], pattern):
matches.append(os.path.join(root, filename))
return matches
Así que si tienes la siguiente estructura dir.
tests/files
├── a0
│ ├── a0.txt
│ ├── a0.yaml
│ └── b0
│ ├── b0.yaml
│ └── b00.yaml
└── a1
Puedes hacer algo como esto
files = utils.find_files(''tests/files'',''**/b0/b*.yaml'')
> [''tests/files/a0/b0/b0.yaml'', ''tests/files/a0/b0/b00.yaml'']
Más o menos la fnmatch
patrón de fnmatch
en el nombre de archivo completo, en lugar de solo el nombre de archivo.
Quiero abrir una serie de subcarpetas en una carpeta y encontrar algunos archivos de texto e imprimir algunas líneas de los archivos de texto. Estoy usando esto:
configfiles = glob.glob(''C:/Users/sam/Desktop/file1/*.txt'')
Pero esto tampoco puede acceder a las subcarpetas. ¿Alguien sabe cómo puedo usar el mismo comando para acceder a las subcarpetas también?
Como señaló Martijn, glob solo puede hacer esto a través del operador **
introducido en Python 3.5. Dado que el OP solicitó explícitamente el módulo glob, lo siguiente devolverá un iterador de evaluación perezoso que se comporta de manera similar
import os, glob, itertools
configfiles = itertools.chain.from_iterable(glob.iglob(os.path.join(root,''*.txt''))
for root, dirs, files in os.walk(''C:/Users/sam/Desktop/file1/''))
Tenga en cuenta que solo puede iterar una vez sobre los configfiles
de configfiles
en este enfoque. Si necesita una lista real de archivos de configuración que se pueden usar en múltiples operaciones, tendría que crear esto explícitamente mediante la list(configfiles)
.
El paquete glob2 admite comodines y es razonablemente rápido.
code = ''''''
import glob2
glob2.glob("files/*/**")
''''''
timeit.timeit(code, number=1)
En mi computadora portátil, toma aproximadamente 2 segundos coincidir con > 60,000 rutas de archivos .
En Python 3.5 y versiones posteriores, utilice la nueva funcionalidad recursiva **/
:
configfiles = glob.glob(''C:/Users/sam/Desktop/file1/**/*.txt'', recursive=True)
Cuando se establece recursive
, **
seguido de un separador de ruta coincide con 0 o más subdirectorios.
En versiones anteriores de Python, glob.glob()
no puede listar archivos en subdirectorios recursivamente.
En ese caso, usaría os.walk()
combinado con fnmatch.filter()
lugar:
import os
import fnmatch
path = ''C:/Users/sam/Desktop/file1''
configfiles = [os.path.join(dirpath, f)
for dirpath, dirnames, files in os.walk(path)
for f in fnmatch.filter(files, ''*.txt'')]
Esto recorrerá los directorios de forma recursiva y devolverá todas las rutas de acceso absolutas a los archivos .txt
correspondientes. En este caso específico, fnmatch.filter()
puede ser excesivo, también podría usar una prueba de .endswith()
:
import os
path = ''C:/Users/sam/Desktop/file1''
configfiles = [os.path.join(dirpath, f)
for dirpath, dirnames, files in os.walk(path)
for f in files if f.endswith(''.txt'')]
Para buscar archivos en subdirectorios inmediatos:
configfiles = glob.glob(r''C:/Users/sam/Desktop/*/*.txt'')
Para una versión recursiva que atraviesa todos los subdirectorios, puedes usar **
y pasar recursive=True
desde Python 3.5 :
configfiles = glob.glob(r''C:/Users/sam/Desktop/**/*.txt'', recursive=True)
Ambas llamadas de función devuelven listas. Podría usar glob.iglob()
para devolver las rutas una por una. O use pathlib
:
from pathlib import Path
path = Path(r''C:/Users/sam/Desktop'')
txt_files_only_subdirs = path.glob(''*/*.txt'')
txt_files_all_recursively = path.rglob(''*.txt'') # including the current dir
Ambos métodos devuelven iteradores (puede obtener rutas uno por uno).
Puedes usar Formic con Python 2.6
import formic
fileset = formic.FileSet(include="**/*.txt", directory="C:/Users/sam/Desktop/")
Divulgación - Soy el autor de este paquete.
Si está ejecutando Python 3.4+, puede usar el módulo pathlib
. El método Path.glob()
admite el patrón **
, que significa "este directorio y todos los subdirectorios, recursivamente". Devuelve un generador que Path
objetos de Path
para todos los archivos coincidentes.
from pathlib import Path
configfiles = Path("C:/Users/sam/Desktop/file1/").glob("**/*.txt")
Si puedes instalar el paquete glob2 ...
import glob2
filenames = glob2.glob("C://top_directory//**//*.ext") # Where ext is a specific file extension
folders = glob2.glob("C://top_directory//**//")
Todos los nombres de archivos y carpetas:
all_ff = glob2.glob("C://top_directory//**//**")
configfiles = glob.glob(''C:/Users/sam/Desktop/**/*.txt")
No funciona para todos los casos, en su lugar usa glob2
configfiles = glob2.glob(''C:/Users/sam/Desktop/**/*.txt")