Ben Gartner
Me gustaría enumerar todos los archivos recursivamente en un directorio. Actualmente tengo una estructura de directorios como esta:
src/main.c
src/dir/file1.c
src/another-dir/file2.c
src/another-dir/nested/files/file3.c
He intentado hacer lo siguiente:
from glob import glob
glob(os.path.join('src','*.c'))
Pero esto solo obtendrá archivos directamente en el src
subcarpeta, por ejemplo, obtengo main.c
pero no voy a conseguir file1.c
, file2.c
etc.
from glob import glob
glob(os.path.join('src','*.c'))
glob(os.path.join('src','*','*.c'))
glob(os.path.join('src','*','*','*.c'))
glob(os.path.join('src','*','*','*','*.c'))
Pero esto es obviamente limitado y torpe, ¿cómo puedo hacerlo correctamente?
johan dahlin
Hay un par de maneras:
pathlib.Path().rglob()
Usar pathlib.Path().rglob()
desde el pathlib
módulo, que se introdujo en Python 3.5.
from pathlib import Path
for path in Path('src').rglob('*.c'):
print(path.name)
globo.glob()
Si no quieres usar pathlib, usa glob.glob()
:
from glob import glob
for filename in glob('src/**/*.c', recursive=True):
print(filename)
Para los casos en los que los archivos coincidentes comienzan con un punto (.
); como archivos en el directorio actual o archivos ocultos en un sistema basado en Unix, use el os.walk()
solución a continuación.
os.caminar()
Para versiones anteriores de Python, use os.walk()
para recorrer recursivamente un directorio y fnmatch.filter()
para hacer coincidir con una expresión simple:
import fnmatch
import os
matches = []
for root, dirnames, filenames in os.walk('src'):
for filename in fnmatch.filter(filenames, '*.c'):
matches.append(os.path.join(root, filename))
Esta versión también debería ser más rápida según la cantidad de archivos que tenga, ya que el módulo pathlib tiene un poco de sobrecarga. os.walk()
.
-
Para Python anterior a 2.2 hay
os.path.walk()
que es un poco más complicado de usar queos.walk()
– John LaRooy
2 de febrero de 2010 a las 19:34
-
@gnibbler Sé que es un comentario antiguo, pero mi comentario es solo para que la gente sepa que
os.path.walk()
está en desuso y se ha eliminado en Python 3.– Pedro Cunha
18 de enero de 2013 a las 16:14
-
@DevC que podría funcionar en el caso específico planteado en esta pregunta, pero es fácil imaginar a alguien que quiera usarlo con consultas como ‘a*.c’, etc., por lo que creo que vale la pena mantener la respuesta actual algo lenta.
– Johan Dahlin
19 mayo 2014 a las 19:29
-
Por lo que vale, en mi caso, encontrar más de 10,000 archivos con glob fue mucho más lento que con os.walk, así que opté por la última solución por ese motivo.
– Godsmith
12 de septiembre de 2018 a las 6:23
-
Para pitón 3.4,
pathlib.Path('src').glob('**/*.c')
Deberia trabajar.– CivFan
11 de abril de 2019 a las 0:16
Pedro Lobito
Para pitón >= 3.5 puedes usar **
, recursive=True
es decir:
import glob
for f in glob.glob('/path/**/*.c', recursive=True):
print(f)
Si es recursivo
True
(por defectoFalse
), el patrón**
coincidirá con cualquier archivo y cero o másdirectories
ysubdirectories
. Si el patrón es seguido por unos.sep
solo directorios ysubdirectories
fósforo.
-
Esto funciona mejor que pathlib.Path(‘./path/’).glob(‘*/‘) porque también lo está en una carpeta con un tamaño de 0
– Charles Walker
18 de abril de 2020 a las 15:14
-
En Python 3.9.1, recursivo se establece en Falso de forma predeterminada.
– PYB
30 de diciembre de 2020 a las 21:53
-
recursive
también está configurado paraFalse
por defecto en Python 3.8.*.– rayryeng
25 oct 2021 a las 14:01
Bruno Oliveira
Similar a otras soluciones, pero usando fnmatch.fnmatch en lugar de glob, ya que os.walk ya enumeró los nombres de archivo:
import os, fnmatch
def find_files(directory, pattern):
for root, dirs, files in os.walk(directory):
for basename in files:
if fnmatch.fnmatch(basename, pattern):
filename = os.path.join(root, basename)
yield filename
for filename in find_files('src', '*.c'):
print 'Found C source:', filename
Además, el uso de un generador le permite procesar cada archivo a medida que se encuentra, en lugar de buscar todos los archivos. y luego procesándolos.
milagro2k
Modifiqué el módulo glob para admitir ** para globbing recursivo, por ejemplo:
>>> import glob2
>>> all_header_files = glob2.glob('src/**/*.c')
https://github.com/miracle2k/python-glob2/
Útil cuando desea proporcionar a sus usuarios la capacidad de usar la sintaxis ** y, por lo tanto, os.walk() por sí solo no es lo suficientemente bueno.
taleinat
Comenzando con Python 3.4, uno puede usar el glob()
método de uno de los Path
clases en el nuevo rutalib módulo, que soporta **
comodines. Por ejemplo:
from pathlib import Path
for file_path in Path('src').glob('**/*.c'):
print(file_path) # do whatever you need with these files
Actualizar:
A partir de Python 3.5, la misma sintaxis también es compatible con glob.glob()
.
-
De hecho, y estará en Python 3.5. Se suponía que ya era así en Python 3.4, pero fue omitido por error.
– taleinat
24 de febrero de 2015 a las 17:39
-
Esta sintaxis es ahora compatible con glob.glob() a partir de Python 3.5.
– taleinat
04/08/2015 a las 15:20
-
Tenga en cuenta que también puede utilizar pathlib.PurePath.relative_to en combinación para obtener rutas relativas. Vea mi respuesta aquí para más contexto.
– pjgranahan
24 de abril de 2017 a las 23:11
Sebastián Mach
import os
import fnmatch
def recursive_glob(treeroot, pattern):
results = []
for base, dirs, files in os.walk(treeroot):
goodfiles = fnmatch.filter(files, pattern)
results.extend(os.path.join(base, f) for f in goodfiles)
return results
fnmatch
te da exactamente los mismos patrones que glob
por lo que este es realmente un excelente reemplazo para glob.glob
con una semántica muy cercana. Una versión iterativa (por ejemplo, un generador), IOW un reemplazo para glob.iglob
es una adaptación trivial (solo yield
los resultados intermedios sobre la marcha, en lugar de extend
ing una sola lista de resultados para volver al final).
-
De hecho, y estará en Python 3.5. Se suponía que ya era así en Python 3.4, pero fue omitido por error.
– taleinat
24 de febrero de 2015 a las 17:39
-
Esta sintaxis es ahora compatible con glob.glob() a partir de Python 3.5.
– taleinat
04/08/2015 a las 15:20
-
Tenga en cuenta que también puede utilizar pathlib.PurePath.relative_to en combinación para obtener rutas relativas. Vea mi respuesta aquí para más contexto.
– pjgranahan
24 de abril de 2017 a las 23:11
Geoff Reedy
Querrás usar os.walk
para recopilar nombres de archivo que coincidan con sus criterios. Por ejemplo:
import os
cfiles = []
for root, dirs, files in os.walk('src'):
for file in files:
if file.endswith('.c'):
cfiles.append(os.path.join(root, file))
no
glob('src/**/*.c')
funciona en este caso?–Likith Reddy
13 de septiembre de 2021 a las 8:06