¿Cómo utilizar para buscar archivos de forma recursiva?
Me gustaría enumerar todos los archivos de forma recursiva 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
Intenté hacer lo siguiente:
from glob import glob
glob(os.path.join('src','*.c'))
Pero esto solo obtendrá archivos directamente en la src
subcarpeta, por ejemplo, obtengo main.c
pero no obtendré 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 complicado, ¿cómo puedo hacerlo correctamente?
Hay un par de maneras:
rutalib.Ruta().rglob()
Úselo 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)
glob.glob()
Si no desea utilizar pathlib, utilice 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 la os.walk()
siguiente solución.
os.walk()
Para versiones anteriores de Python, utilícelo os.walk()
para recorrer recursivamente un directorio y fnmatch.filter()
compararlo 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 dependiendo de cuántos archivos tenga, ya que el módulo pathlib tiene un poco de sobrecarga sobre os.walk()
.
Para Python >= 3.5 puedes usar **
, recursive=True
, es decir:
import glob
for f in glob.glob('/path/**/*.c', recursive=True):
print(f)
Si recursivo es
True
(predeterminadoFalse
), el patrón**
coincidirá con cualquier archivo y cero o másdirectories
ysubdirectories
. Si el patrón va seguido deos.sep
, solo directorios ysubdirectories
coincidencias.
Demostración de Python 3
Similar a otras soluciones, pero usando fnmatch.fnmatch en lugar de glob, ya que os.walk ya enumera los nombres de archivos:
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 tal como se encuentra, en lugar de buscar todos los archivos y luego procesarlos.
Modifiqué el módulo glob para admitir ** el globbing recursivo, por ejemplo:
>>> import glob2
>>> all_header_files = glob2.glob('src/**/*.c')
https://github.com/miracle2k/python-glob2/
Útil cuando desea brindarles a sus usuarios la capacidad de usar la sintaxis ** y, por lo tanto, os.walk() por sí solo no es lo suficientemente bueno.
A partir de Python 3.4, se puede utilizar el glob()
método de una de las Path
clases del nuevo módulo pathlib , que admite **
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
Actualización:
a partir de Python 3.5, la misma sintaxis también es compatible con glob.glob()
.