Tengo un fondo C ++ / Obj-C y estoy descubriendo Python (lo he estado escribiendo durante aproximadamente una hora). Estoy escribiendo un script para leer recursivamente el contenido de los archivos de texto en una estructura de carpetas.
El problema que tengo es que el código que he escrito solo funcionará para una carpeta de profundidad. Puedo ver por qué en el código (ver #hardcoded path
), simplemente no sé cómo puedo avanzar con Python ya que mi experiencia con él es completamente nueva.
Código de Python:
import os
import sys
rootdir = sys.argv[1]
for root, subFolders, files in os.walk(rootdir):
for folder in subFolders:
outfileName = rootdir + "/" + folder + "/py-outfile.txt" # hardcoded path
folderOut = open( outfileName, 'w' )
print "outfileName is " + outfileName
for file in files:
filePath = rootdir + '/' + file
f = open( filePath, 'r' )
toWrite = f.read()
print "Writing '" + toWrite + "' to" + filePath
folderOut.write( toWrite )
f.close()
folderOut.close()
os.walk
no está mal, aunque se me ocurrió una forma aún más rápidaos.scandir
. Todas lasglob
soluciones son mucho más lentas quewalk
&scandir
. Mi función, así como un análisis de velocidad completo, se puede encontrar aquí: stackoverflow.com/a/59803793/2441026Si está utilizando Python 3.5 o superior, puede hacerlo en 1 línea.
Como se menciona en la documentación
Si desea cada archivo, puede usar
fuente
root_dir
necesita una barra diagonal final? Esto ahorrará tiempo a la gente (o al menos me habría ahorrado tiempo). Gracias.glob.iglob(root_dir + '**/**', recursive=True)
. Estoy trabajando en Python 3.8.2De acuerdo con Dave Webb,
os.walk
producirá un elemento para cada directorio en el árbol. El hecho es que no tienes que preocupartesubFolders
.Un código como este debería funcionar:
fuente
TL; DR: Esto es equivalente a
find -type f
revisar todos los archivos en todas las carpetas a continuación e incluir la actual:Como ya se mencionó en otras respuestas,
os.walk()
es la respuesta, pero podría explicarse mejor. ¡Es bastante simple! Pasemos por este árbol:Con este código:
La
currentpath
es la carpeta actual que está mirando. Esto generará:Entonces se repite tres veces, porque hay tres carpetas: la actual
docs
, ypics
. En cada bucle, llena las variablesfolders
yfiles
con todas las carpetas y archivos. Vamos a mostrarlesEsto nos muestra:
Así, en la primera línea, vemos que estamos en la carpeta
.
, que contiene dos carpetas a saberpics
ydocs
, y que hay un solo archivo, a sabertodo.txt
. No tiene que hacer nada para recurrir a esas carpetas, porque, como puede ver, se repite automáticamente y solo le da los archivos en cualquier subcarpeta. Y cualquier subcarpeta de eso (aunque no las tenemos en el ejemplo).Si solo desea recorrer todos los archivos, el equivalente de
find -type f
, puede hacer esto:Esto produce:
fuente
La
pathlib
biblioteca es realmente genial para trabajar con archivos. Puedes hacer un globo recursivo en unPath
objeto así.fuente
Si desea una lista plana de todas las rutas bajo un directorio dado (como
find .
en el shell):Para incluir solo rutas completas a los archivos bajo el directorio base, omita
+ subdirs
.fuente
**/**
se utiliza para obtener todos los archivos de forma recursiva, incluidosdirectory
.if os.path.isfile(filename)
se usa para verificar si lafilename
variable esfile
odirectory
, si es un archivo, entonces podemos leer ese archivo. Aquí estoy imprimiendo el archivo.fuente
He encontrado que lo siguiente es lo más fácil
El uso
glob('some/path/**', recursive=True)
obtiene todos los archivos, pero también incluye los nombres de directorio. Agregar laif os.path.isfile(f)
condición filtra esta lista solo a los archivos existentesfuente
use
os.path.join()
para construir sus caminos - Es más ordenado:fuente
os.walk
hace caminata recursiva por defecto. Para cada directorio, comenzando desde la raíz, produce una tupla de 3 (dirpath, dirnames, nombres de archivo)fuente
walk()
, devuelve la lista recursiva. Probé su código y obtuve una lista con muchas repeticiones ... Si solo elimina las líneas debajo del comentario "# llamadas recursivas en subcarpetas" - funciona bienPrueba esto:
fuente
Creo que el problema es que no estás procesando la salida
os.walk
correctamente.En primer lugar, cambiar:
a:
rootdir
es su directorio de inicio fijo;root
es un directorio devuelto poros.walk
.En segundo lugar, no necesita sangrar el bucle de procesamiento de archivos, ya que no tiene sentido ejecutar esto para cada subdirectorio. Se
root
establecerá en cada subdirectorio. No necesita procesar los subdirectorios a mano, a menos que quiera hacer algo con los directorios en sí.fuente
filePath = rootdir + '/' + file
, eso no suena bien: ¿el archivo es de la lista de archivos actuales, entonces estás escribiendo en muchos archivos existentes?