Recorrer árboles de directorios es una tarea habitual en automatizaciones, herramientas de línea de comandos, sistemas de copias de seguridad, analizadores de código y organizadores de archivos. Durante años, la solución más conocida en Python fue os.walk(). Desde Python 3.12, la clase Path del módulo pathlib también incluye el método Path.walk(), que lleva el recorrido recursivo a una API orientada a objetos. En esta guía aprenderás a usar pathlib.Path.walk en Python, a compararlo con os.walk() y a aplicarlo de forma segura en proyectos reales.
¿Qué es pathlib.Path.walk?
Path.walk() recorre un árbol de directorios y produce una tupla de tres elementos por cada carpeta: el directorio actual, una lista con los nombres de las subcarpetas y una lista con los nombres de los archivos. Su estructura se parece a os.walk(), pero el directorio actual es un objeto Path. Esto facilita unir rutas, revisar extensiones, leer archivos o consultar metadatos sin convertir cadenas manualmente.
from pathlib import Path
raiz = Path("proyecto")
for directorio, carpetas, archivos in raiz.walk():
print("Directorio:", directorio)
print("Carpetas:", carpetas)
print("Archivos:", archivos)
Si todavía no conoces bien esta API, revisa la introducción de Academify sobre manipulación de archivos con pathlib. Entender los objetos Path y el operador / hará que los siguientes ejemplos sean más claros.
Cómo construir la ruta completa
Los nombres de archivo devueltos son cadenas. Para obtener la ruta completa, combina cada nombre con el directorio actual.
from pathlib import Path
for directorio, carpetas, archivos in Path("datos").walk():
for nombre in archivos:
ruta = directorio / nombre
print(ruta)
Este enfoque funciona en Windows, macOS y Linux porque pathlib utiliza el separador correcto para cada sistema. También es más legible que concatenar texto con barras. Si tu script no encuentra una ruta, consulta la guía de Academify sobre FileNotFoundError en Python.
Filtrar archivos por extensión
Un caso muy frecuente consiste en localizar solo archivos de un tipo determinado. Como la ruta completa es un objeto Path, puedes usar la propiedad suffix.
from pathlib import Path
for directorio, carpetas, archivos in Path("informes").walk():
for nombre in archivos:
archivo = directorio / nombre
if archivo.suffix.lower() == ".csv":
print(archivo)
La llamada a lower() también reconoce variantes como .CSV. Después de encontrar los archivos, puedes procesarlos con las técnicas del tutorial sobre archivos CSV en Python.
Omitir carpetas durante el recorrido
Cuando el recorrido se realiza de arriba hacia abajo, puedes modificar la lista carpetas en el mismo lugar. Al eliminar nombres de esa lista, el método no entra en esos directorios. Esto resulta útil para entornos virtuales, cachés, dependencias y metadatos de control de versiones.
from pathlib import Path
ignoradas = {".git", ".venv", "__pycache__", "node_modules"}
for directorio, carpetas, archivos in Path("mi_proyecto").walk(top_down=True):
carpetas[:] = [c for c in carpetas if c not in ignoradas]
print(directorio)
La asignación mediante una porción es importante porque modifica la lista original utilizada internamente. Crear otra variable no podaría el recorrido. Filtrar temprano puede ahorrar mucho tiempo cuando un proyecto contiene miles de archivos de dependencias o caché.
top_down y bottom_up
El argumento top_down controla el orden. Su valor predeterminado es True, de modo que el directorio padre aparece antes que sus hijos. Con False, los directorios más profundos aparecen primero.
from pathlib import Path
for directorio, carpetas, archivos in Path("temporales").walk(top_down=False):
print(directorio)
El recorrido de abajo hacia arriba es útil para borrar árboles, ya que el contenido debe eliminarse antes que la carpeta principal. El recorrido de arriba hacia abajo es mejor cuando quieres excluir subdirectorios antes de visitarlos. La modificación de la lista de carpetas controla la navegación únicamente en el modo descendente.
Gestionar errores de acceso
Un árbol puede contener ubicaciones que el usuario actual no puede leer. El argumento on_error acepta una función que recibe el error del sistema operativo.
from pathlib import Path
def registrar_error(error):
print(f"No se pudo acceder a: {error.filename}")
for directorio, carpetas, archivos in Path("/datos").walk(on_error=registrar_error):
print(directorio)
Registrar los errores es esencial en copias de seguridad y auditorías. De lo contrario, un proceso podría terminar sin informar que omitió una parte del árbol. La guía sobre PermissionError en Python explica las causas habituales de los problemas de permisos.
Contar archivos y calcular el tamaño
Puedes combinar walk() con stat() para crear un resumen de almacenamiento.
from pathlib import Path
cantidad = 0
total_bytes = 0
for directorio, carpetas, archivos in Path("backup").walk():
for nombre in archivos:
ruta = directorio / nombre
try:
total_bytes += ruta.stat().st_size
cantidad += 1
except OSError as error:
print("Fallo:", ruta, error)
print("Archivos:", cantidad)
print("Tamaño:", total_bytes, "bytes")
El bloque de excepción protege contra condiciones de carrera. Un archivo puede borrarse, cambiar de nombre o perder permisos después de ser listado y antes de ejecutar stat().
Path.walk frente a os.walk
Ambas APIs siguen un modelo generador parecido, pero no son idénticas. Path.walk() produce un objeto Path para la raíz actual, mientras que os.walk() devuelve cadenas. El tratamiento de enlaces simbólicos y la clasificación de determinadas entradas también puede variar. Por ello, no sustituyas una función por otra sin probar el comportamiento esperado.
La documentación oficial de Path.walk explica sus parámetros y casos especiales. La referencia de os.walk permite comparar las dos soluciones.
Enlaces simbólicos y riesgo de ciclos
El argumento follow_symlinks controla si se recorren enlaces simbólicos que apuntan a directorios. El valor predeterminado es False. Activarlo requiere cuidado porque un enlace puede apuntar a un directorio superior y generar un ciclo infinito. El método no mantiene automáticamente un registro completo de todos los directorios visitados.
from pathlib import Path
for directorio, carpetas, archivos in Path("datos").walk(follow_symlinks=False):
pass
En herramientas de backup, limpieza o indexación, conservar el valor predeterminado suele ser más seguro. Si necesitas seguir enlaces, registra rutas resueltas o identificadores del sistema de archivos para evitar visitar el mismo directorio más de una vez.
Ejemplo práctico: organizar por extensión
El siguiente script recorre una carpeta de entrada y mueve cada archivo a una subcarpeta cuyo nombre corresponde a la extensión.
from pathlib import Path
import shutil
origen = Path("entrada")
destino = Path("organizados")
for directorio, carpetas, archivos in origen.walk():
for nombre in archivos:
archivo = directorio / nombre
extension = archivo.suffix.lower().lstrip(".") or "sin_extension"
carpeta_destino = destino / extension
carpeta_destino.mkdir(parents=True, exist_ok=True)
shutil.move(str(archivo), carpeta_destino / archivo.name)
Prueba primero con copias. Los conflictos de nombre, permisos y cambios durante la ejecución pueden producir resultados inesperados. El tutorial sobre copiar y mover archivos con shutil presenta precauciones adicionales.
Consideraciones de rendimiento
Path.walk() produce resultados de forma perezosa, por lo que no es necesario guardar todo el árbol en memoria. Procesa cada directorio cuando aparece, excluye carpetas irrelevantes cuanto antes y evita llamar a stat() cuando no necesites metadatos. En unidades de red, cada consulta puede ser costosa; reducir accesos al sistema de archivos suele ser más importante que pequeñas optimizaciones del código Python.
Buenas prácticas
Valida la raíz antes de comenzar, filtra directorios temprano, captura OSError y evita recorrer enlaces simbólicos salvo que sea necesario. Normaliza las extensiones antes de compararlas. Para scripts destructivos, incorpora un modo de simulación que muestre las acciones previstas antes de cambiar archivos. También registra errores y cantidades para comprobar que el proceso analizó el volumen esperado.
Conclusión
pathlib.Path.walk ofrece una forma moderna y legible de recorrer árboles de directorios en Python 3.12 o superior. Se integra con las operaciones de Path, permite controlar el orden, excluir carpetas y manejar errores explícitamente. En proyectos nuevos que ya utilizan pathlib, puede ser una alternativa excelente a os.walk(). La clave consiste en combinar la comodidad de la API con precauciones frente a permisos, condiciones de carrera, enlaces y operaciones destructivas.







