Directorio de lista de Python, subdirectorio y archivos

130

Estoy tratando de hacer un script para enumerar todos los directorios, subdirectorios y archivos en un directorio dado.
Intenté esto:

import sys,os

root = "/home/patate/directory/"
path = os.path.join(root, "targetdirectory")

for r,d,f in os.walk(path):
    for file in f:
        print os.path.join(root,file)

Desafortunadamente no funciona correctamente.
Obtengo todos los archivos, pero no sus rutas completas.

Por ejemplo, si la estructura dir sería:

/home/patate/directory/targetdirectory/123/456/789/file.txt

Imprimiría:

/home/patate/directory/targetdirectory/file.txt

Lo que necesito es el primer resultado. Cualquier ayuda sería muy apreciada! Gracias.

thomytheyon
fuente

Respuestas:

225

Use os.path.joinpara concatenar el directorio y el nombre del archivo :

for path, subdirs, files in os.walk(root):
    for name in files:
        print os.path.join(path, name)

Tenga en cuenta el uso de pathy no rooten la concatenación, ya que el uso rootsería incorrecto.


En Python 3.4, se agregó el módulo pathlib para facilitar la manipulación de rutas. Entonces el equivalente a os.path.joinsería:

pathlib.PurePath(path, name)

La ventaja de pathlibes que puede utilizar una variedad de métodos útiles en las rutas. Si usa la Pathvariante concreta , también puede hacer llamadas reales del sistema operativo a través de ellas, como chatear en un directorio, eliminar la ruta, abrir el archivo al que apunta y mucho más.

Eli Bendersky
fuente
Esta es la única respuesta útil para las muchas preguntas que se han formulado con respecto a "cómo obtener todos los archivos de forma recursiva en Python".
harrisonfooord
lista de comprensión: all_files = [os.path.join (ruta, nombre) para nombre en archivos para ruta, subdirectorios, archivos en os.walk (carpeta)]
Nir
45

Por si acaso ... Obtener todos los archivos en el directorio y subdirectorios que coincidan con algún patrón (* .py por ejemplo):

import os
from fnmatch import fnmatch

root = '/some/directory'
pattern = "*.py"

for path, subdirs, files in os.walk(root):
    for name in files:
        if fnmatch(name, pattern):
            print os.path.join(path, name)
Ivan
fuente
10

Aquí hay una frase:

import os

[val for sublist in [[os.path.join(i[0], j) for j in i[2]] for i in os.walk('./')] for val in sublist]
# Meta comment to ease selecting text

El val for sublist in ...bucle más externo aplana la lista para que sea unidimensional. El jbucle recopila una lista de cada nombre base de archivo y lo une a la ruta actual. Finalmente, el iciclo itera sobre todos los directorios y subdirectorios.

Este ejemplo utiliza la ruta codificada ./en la os.walk(...)llamada, puede complementar cualquier cadena de ruta que desee.

Nota: os.path.expandusery / o os.path.expandvarspuede usarse para cadenas de rutas como~/

Extendiendo este ejemplo:

Es fácil agregar en las pruebas de nombre de base de archivo y pruebas de nombre de directorio.

Por ejemplo, prueba de *.jpgarchivos:

... for j in i[2] if j.endswith('.jpg')] ...

Además, excluyendo el .gitdirectorio:

... for i in os.walk('./') if '.git' not in i[0].split('/')]
ThorSummoner
fuente
Funciona, pero para excluir .git directoy debe verificar si '.git' NO está en la ruta.
Roman Rdgz
Sí. Debería ser si '.git' no está en i [0] .split ('/')]
Roman Rdgz
Recomendaría os.walksobre un bucle de dirlisting manual, los generadores son geniales, ve a usarlos.
ThorSummoner
9

No se pudo comentar, así que escribe la respuesta aquí. Esta es la línea más clara que he visto:

import os
[os.path.join(path, name) for path, subdirs, files in os.walk(root) for name in files]
Mong H. Ng
fuente
4

Puedes echar un vistazo a esta muestra que hice. Utiliza la función os.path.walk, que está en desuso, tenga cuidado. Utiliza una lista para almacenar todas las rutas de archivo

root = "Your root directory"
ex = ".txt"
where_to = "Wherever you wanna write your file to"
def fileWalker(ext,dirname,names):
    '''
    checks files in names'''
    pat = "*" + ext[0]
    for f in names:
        if fnmatch.fnmatch(f,pat):
            ext[1].append(os.path.join(dirname,f))


def writeTo(fList):

    with open(where_to,"w") as f:
        for di_r in fList:
            f.write(di_r + "\n")






if __name__ == '__main__':
    li = []
    os.path.walk(root,fileWalker,[ex,li])

    writeTo(li)
devsaw
fuente
4

Un poco más simple:

import os
from itertools import product, chain

chain.from_iterable([[os.sep.join(w) for w in product([i[0]], i[2])] for i in os.walk(dir)])
Daniel
fuente
2

Como cada ejemplo aquí solo está usando walk(con join), me gustaría mostrar un buen ejemplo y una comparación con listdir:

import os, time

def listFiles1(root): # listdir
    allFiles = []; walk = [root]
    while walk:
        folder = walk.pop(0)+"/"; items = os.listdir(folder) # items = folders + files
        for i in items: i=folder+i; (walk if os.path.isdir(i) else allFiles).append(i)
    return allFiles

def listFiles2(root): # listdir/join (takes ~1.4x as long) (and uses '\\' instead)
    allFiles = []; walk = [root]
    while walk:
        folder = walk.pop(0); items = os.listdir(folder) # items = folders + files
        for i in items: i=os.path.join(folder,i); (walk if os.path.isdir(i) else allFiles).append(i)
    return allFiles

def listFiles3(root): # walk (takes ~1.5x as long)
    allFiles = []
    for folder, folders, files in os.walk(root):
        for file in files: allFiles+=[folder.replace("\\","/")+"/"+file] # folder+"\\"+file still ~1.5x
    return allFiles

def listFiles4(root): # walk/join (takes ~1.6x as long) (and uses '\\' instead)
    allFiles = []
    for folder, folders, files in os.walk(root):
        for file in files: allFiles+=[os.path.join(folder,file)]
    return allFiles


for i in range(100): files = listFiles1("src") # warm up

start = time.time()
for i in range(100): files = listFiles1("src") # listdir
print("Time taken: %.2fs"%(time.time()-start)) # 0.28s

start = time.time()
for i in range(100): files = listFiles2("src") # listdir and join
print("Time taken: %.2fs"%(time.time()-start)) # 0.38s

start = time.time()
for i in range(100): files = listFiles3("src") # walk
print("Time taken: %.2fs"%(time.time()-start)) # 0.42s

start = time.time()
for i in range(100): files = listFiles4("src") # walk and join
print("Time taken: %.2fs"%(time.time()-start)) # 0.47s

Como puede ver por usted mismo, la listdirversión es mucho más eficiente. (y eso joines lento)

Charco
fuente