2008-09-26 16 views
86

Quiero ser capaz de enumerar solo los directorios dentro de alguna carpeta. Esto significa que no quiero que aparezcan los nombres de los archivos, ni quiero otras subcarpetas.¿Cómo enumerar solo los directorios de nivel superior en Python?

Veamos si un ejemplo ayuda. En el directorio actual tenemos:

>>> os.listdir(os.getcwd()) 
['cx_Oracle-doc', 'DLLs', 'Doc', 'include', 'Lib', 'libs', 'LICENSE.txt', 'mod_p 
ython-wininst.log', 'NEWS.txt', 'pymssql-wininst.log', 'python.exe', 'pythonw.ex 
e', 'README.txt', 'Removemod_python.exe', 'Removepymssql.exe', 'Scripts', 'tcl', 
'Tools', 'w9xpopen.exe'] 

Sin embargo, no quiero los nombres de los archivos listados. Tampoco quiero subcarpetas como \ Lib \ maldiciones. Esencialmente lo que quiero funciona con las siguientes:

>>> for root, dirnames, filenames in os.walk('.'): 
...  print dirnames 
...  break 
... 
['cx_Oracle-doc', 'DLLs', 'Doc', 'include', 'Lib', 'libs', 'Scripts', 'tcl', 'Tools'] 

Sin embargo, me pregunto si hay una manera más sencilla de lograr los mismos resultados. Me da la impresión de que usar os.walk solo para devolver el nivel superior es ineficiente/demasiado.

Respuesta

76

Filtrar el resultado utilizando os.path.isdir() (y utilizar os.path.join() para obtener la ruta real):

>>> [ name for name in os.listdir(thedir) if os.path.isdir(os.path.join(thedir, name)) ] 
['ctypes', 'distutils', 'encodings', 'lib-tk', 'config', 'idlelib', 'xml', 'bsddb', 'hotshot', 'logging', 'doc', 'test', 'compiler', 'curses', 'site-packages', 'email', 'sqlite3', 'lib-dynload', 'wsgiref', 'plat-linux2', 'plat-mac'] 
+11

Esto requiere mucho procesamiento vs muy simple os.walk() .next() [1] –

11
directories=[d for d in os.listdir(os.getcwd()) if os.path.isdir(d)] 
+4

Esto puede ser acortado a filtrar (os.path.isdir, os.listdir (os.getcwd()) –

+0

Creo que la lista por comprensión es más fácil de leer. – nosklo

+3

¿alguien tiene alguna información sobre si el filtro o una lista de comprensión es más rápido? De lo contrario, es sólo un argumento subjetivo. Por supuesto, supone que hay 10 millones de directorios en el cwd y el rendimiento es un problema. –

0

Me gusta?

>>> [ruta para la ruta en os.listdir (os.getcwd()) si os.path.isdir (ruta de acceso)]

1
[x for x in os.listdir(somedir) if os.path.isdir(os.path.join(somedir, x))] 
35

Filtrar la lista mediante os.path.isdir para detectar directorios.

filter(os.path.isdir, os.listdir(os.getcwd())) 
+4

Creo que esta es de lejos la mejor combinación de legibilidad y concisión en cualquiera de estas respuestas. – vergenzt

+8

Esto no funcionó. Supongo que 'os.listdir' devuelve un nombre de archivo/carpeta, pasado a' os.path.isdir', pero este último necesita una ruta completa. –

+2

filtro es más rápido que os.walk '' timeit '1000 bucles, mejor de 3 (os.walk (os.getcwd()) Siguiente() [1].): 734 mu s por loop' ' timeit (filter (os.path.isdir, os.listdir (os.getcwd()))) ' ' 1000 loops, lo mejor de 3: 477 μs por ciclo' –

8

Tenga en cuenta que, en vez de hacer os.listdir(os.getcwd()), es preferible hacer os.listdir(os.path.curdir). Llamada a una función menos, y es tan portátil.

lo tanto, para completar la respuesta, para obtener una lista de directorios en una carpeta:

def listdirs(folder): 
    return [d for d in os.listdir(folder) if os.path.isdir(os.path.join(folder, d))] 

Si prefiere rutas completas, a continuación, utilizar esta función:

def listdirs(folder): 
    return [ 
     d for d in (os.path.join(folder, d1) for d1 in os.listdir(folder)) 
     if os.path.isdir(d) 
    ] 
127
os.walk('.').next()[1] 

o con Python 3 use

next(os.walk('.'))[1] 

como @Andre Soares dijo en el comentario a continuación.

+12

Un poco más de descripción sobre esto es que este es un generador, no caminará con los otros directorios a menos que se lo digas. Así que .next() [1] hace en una línea lo que hacen todas las listas de comprensión. Probablemente haga algo como 'DIRNAMES = 1' y luego' next() [DIRNAMES] 'para que sea más fácil de entender para futuros mantenedores de código. – boatcoder

+2

+1 solución increíble. Para especificar un directorio para navegar, use: 'os.walk (os.path.join (mypath, '.')) Next() [1]' –

+36

para python v3: next (os.walk ('.')) [1] –

2

ser un novato aquí que no puedo comentar todavía directamente pero aquí es una pequeña corrección Me gustaría añadir a la siguiente parte de ΤΖΩΤΖΙΟΥ's answer:

Si prefiere rutas completas, a continuación, utilizar esta función :

def listdirs(folder): 
    return [ 
    d for d in (os.path.join(folder, d1) for d1 in os.listdir(folder)) 
    if os.path.isdir(d) 
] 

para los que siguen en pitón < 2,4: el constructo interior necesita ser una lista en lugar de una tupla y por lo tanto debe leer como ésimo es:

def listdirs(folder): 
    return [ 
    d for d in [os.path.join(folder, d1) for d1 in os.listdir(folder)] 
    if os.path.isdir(d) 
    ] 

De lo contrario, uno obtiene un error de sintaxis.

+0

sé que ha pasado un tiempo, pero este primer ejemplo realmente me ayudó. –

+1

Obtiene un error de sintaxis porque su versión no admite expresiones de generador. Estos se introdujeron en Python 2.4, mientras que las listas de comprensión han estado disponibles desde Python 2.0. – awatts

+0

@awatts finalmente resolvió un viejo misterio (para mí), ¡gracias! – antiplex

7

Solo para agregar que usar os.listdir() no hace "tomar un montón de procesamiento vs muy simple os.walk(). Next() [1]". Esto se debe a que os.walk() usa os.listdir() internamente. De hecho, si los prueba juntos:

>>>> import timeit 
>>>> timeit.timeit("os.walk('.').next()[1]", "import os", number=10000) 
1.1215229034423828 
>>>> timeit.timeit("[ name for name in os.listdir('.') if os.path.isdir(os.path.join('.', name)) ]", "import os", number=10000) 
1.0592019557952881 

El filtrado de os.listdir() es muy ligeramente más rápido.

+1

Venir en Python 3.5 es una manera más rápida de obtener contenido de directorio: https://www.python.org/dev/peps/pep-0471/ – foz

+0

pep-0471 - el paquete 'scandir' está felizmente disponible para Python 2 .6 en adelante como un paquete instalable en PyPI. Ofrece reemplazos para 'os.walk' y' os.listdir' que son mucho más rápidos. – foz

1

Para obtener una lista de nombres de ruta completos Yo prefiero esta versión a la otra solutions aquí:

def listdirs(dir): 
    return [os.path.join(os.path.join(dir, x)) for x in os.listdir(dir) 
     if os.path.isdir(os.path.join(dir, x))] 
6

Una manera mucho más simple y elegante es utilizar esto:

import os 
dir_list = os.walk('.').next()[1] 
print dir_list 

Ejecutar este proceso en la misma carpeta para la que desea nombres de carpeta. Le dará exactamente el nombre de las carpetas inmediatas solamente (también sin la ruta completa de las carpetas).

4

Esto parece funcionar también (al menos en Linux):

import glob, os 
glob.glob('*' + os.path.sep) 
+0

+1 para 'glob'. Puede ahorrarle mucho código, especialmente iteraciones, y es muy similar al uso de la terminal UNIX ('ls') – Gerard

+0

En lugar de glob.glob ('\ *' + os.path.sep) es posible que desee escribir [ dir para dir en glob.glob ("\ *") si os.path.isdir (dir)] –

0

Una opción más segura que no falla cuando no hay ningún directorio.

def listdirs(folder): 
    if os.path.exists(folder): 
     return [d for d in os.listdir(folder) if os.path.isdir(os.path.join(folder, d))] 
    else: 
     return [] 
0
scanDir = "abc" 
directories = [d for d in os.listdir(scanDir) if os.path.isdir(os.path.join(os.path.abspath(scanDir), d))] 
-1
-- This will exclude files and traverse through 1 level of sub folders in the root 

def list_files(dir): 
    List = [] 
    filterstr = ' ' 
    for root, dirs, files in os.walk(dir, topdown = True): 
     #r.append(root) 
     if (root == dir): 
      pass 
     elif filterstr in root: 
      #filterstr = ' ' 
      pass 
     else: 
      filterstr = root 
      #print(root) 
      for name in files: 
       print(root) 
       print(dirs) 
       List.append(os.path.join(root,name)) 
      #print(os.path.join(root,name),"\n") 
       print(List,"\n") 

    return List 
Cuestiones relacionadas