with - python iter method
¿Cómo puedo atravesar un sistema de archivos con un generador? (6)
¿Por qué reinventar la rueda cuando puedes usar os.walk
import os
for root, dirs, files in os.walk(path):
for name in files:
print os.path.join(root, name)
os.walk es un generador que proporciona los nombres de los archivos en un árbol de directorios al caminar por el árbol de arriba hacia abajo o de abajo hacia arriba
Estoy tratando de crear una clase de utilidad para atravesar todos los archivos en un directorio, incluidos aquellos dentro de los subdirectorios y subdirectorios. Intenté usar un generador porque los generadores son geniales; Sin embargo, me golpeó un obstáculo.
def grab_files(directory):
for name in os.listdir(directory):
full_path = os.path.join(directory, name)
if os.path.isdir(full_path):
yield grab_files(full_path)
elif os.path.isfile(full_path):
yield full_path
else:
print(''Unidentified name %s. It could be a symbolic link'' % full_path)
Cuando el generador llega a un directorio, simplemente genera la ubicación de memoria del nuevo generador; No me da los contenidos del directorio.
¿Cómo puedo hacer que el generador ceda el contenido del directorio en lugar de un nuevo generador?
Si ya existe una función de biblioteca simple para enumerar de forma recursiva todos los archivos en una estructura de directorio, hágamelo saber. No pretendo replicar una función de biblioteca.
A partir de Python 3.4, puede usar el método glob()
desde el módulo de pathlib incorporado:
import pathlib
p = pathlib.Path(''.'')
list(p.glob(''**/*'')) # lists all files recursively
A partir de Python 3.4, puede usar el módulo Pathlib :
In [48]: def alliter(p):
....: yield p
....: for sub in p.iterdir():
....: if sub.is_dir():
....: yield from alliter(sub)
....: else:
....: yield sub
....:
In [49]: g = alliter(pathlib.Path("."))
In [50]: [next(g) for _ in range(10)]
Out[50]:
[PosixPath(''.''),
PosixPath(''.pypirc''),
PosixPath(''.python_history''),
PosixPath(''lshw''),
PosixPath(''.gstreamer-0.10''),
PosixPath(''.gstreamer-0.10/registry.x86_64.bin''),
PosixPath(''.gconf''),
PosixPath(''.gconf/apps''),
PosixPath(''.gconf/apps/gnome-terminal''),
PosixPath(''.gconf/apps/gnome-terminal/%gconf.xml'')]
Esta es la respuesta esencial de la versión orientada a objetos de sjthebats . ¡Tenga en cuenta que el patrón Path.glob **
solo devuelve directorios!
Addendum a la respuesta de gerrit. Quería hacer algo más flexible.
listar todos los archivos en pth
coincidan con un pattern
dado, también puede listar los only_file
si only_file
es False
from pathlib import Path
def walk(pth=Path(''.''), pattern=''*'', only_file=True) :
""" list all files in pth matching a given pattern, can also list dirs if only_file is False """
if pth.match(pattern) and not (only_file and pth.is_dir()) :
yield pth
for sub in pth.iterdir():
if sub.is_dir():
yield from walk(sub, pattern, only_file)
else:
if sub.match(pattern) :
yield sub
Estoy de acuerdo con la solución os.walk
Para fines puramente pedantes, intente iterar sobre el objeto generador, en lugar de devolverlo directamente:
def grab_files(directory):
for name in os.listdir(directory):
full_path = os.path.join(directory, name)
if os.path.isdir(full_path):
for entry in grab_files(full_path):
yield entry
elif os.path.isfile(full_path):
yield full_path
else:
print(''Unidentified name %s. It could be a symbolic link'' % full_path)
Puedes usar path.py Desafortunadamente, el sitio web del autor ya no está disponible, pero aún puede descargar el código desde PyPI. Esta biblioteca es una envoltura alrededor de las funciones de ruta en el módulo os
.
path.py
proporciona un método walkfiles()
que devuelve un generador iterando recursivamente sobre todos los archivos en el directorio:
>>> from path import path
>>> print path.walkfiles.__doc__
D.walkfiles() -> iterator over files in D, recursively.
The optional argument, pattern, limits the results to files
with names that match the pattern. For example,
mydir.walkfiles(''*.tmp'') yields only files with the .tmp
extension.
>>> p = path(''/tmp'')
>>> p.walkfiles()
<generator object walkfiles at 0x8ca75a4>
>>>