web-dev-qa-db-fra.com

Comment lister uniquement les répertoires de premier niveau en Python?

Je veux pouvoir énumérer seulement les répertoires à l'intérieur d'un dossier. Cela signifie que je ne veux pas que les noms de fichiers soient listés, ni de sous-dossiers supplémentaires.

Voyons si un exemple peut aider. Dans le répertoire actuel, nous avons:

>>> 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']

Cependant, je ne veux pas que les noms de fichiers soient listés. Je ne veux pas non plus de sous-dossiers tels que\Lib\curses. Essentiellement, ce que je veux fonctionne avec les éléments suivants:

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

Cependant, je me demande s’il existe un moyen plus simple d’obtenir les mêmes résultats. J'ai l'impression que l'utilisation de os.walk uniquement pour renvoyer le niveau supérieur est inefficace/excessive.

108
fuentesjr

Filtrez le résultat en utilisant os.path.isdir () (et utilisez os.path.join () pour obtenir le vrai chemin):

>>> [ 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']
100
Thomas Wouters

os.walk

Utilisation os.walk avec next fonction de l’élément:

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

Pour Python <= 2.5 , utilisez:

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

Comment ça marche

os.walk est un générateur et appeler next obtiendra le premier résultat sous la forme d'un 3-Tuple (dirpath, dirnames, noms de fichiers). Ainsi, le [1] index ne renvoie que le dirnames de ce tuple.

163
Alex Coventry

Filtrez la liste en utilisant os.path.isdir pour détecter les répertoires.

filter(os.path.isdir, os.listdir(os.getcwd()))
43
Colin Jensen
directories=[d for d in os.listdir(os.getcwd()) if os.path.isdir(d)]
12
Mark Roddy

Notez que, au lieu de os.listdir(os.getcwd()), il est préférable de faire os.listdir(os.path.curdir). Un appel de fonction de moins, et il est aussi portable.

Donc, pour compléter la réponse, obtenir une liste de répertoires dans un dossier:

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

Si vous préférez des chemins d'accès complets, utilisez cette fonction:

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

Juste pour ajouter que l'utilisation de os.listdir () ne fait pas "prend beaucoup de traitement vs très simple os.walk (). Next () [1]". En effet, os.walk () utilise os.listdir () en interne. En fait si vous les testez ensemble:

>>>> 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

Le filtrage de os.listdir () est très légèrement plus rapide.

8
foz

Une manière beaucoup plus simple et élégante consiste à utiliser ceci:

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

Exécutez ce script dans le même dossier pour lequel vous voulez des noms de dossier. Il vous donnera exactement le nom du dossier immédiat uniquement (sans le chemin complet des dossiers).

6
manty

Cela semble fonctionner aussi (au moins sur Linux):

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

Utilisation de la compréhension de liste,

[a for a in os.listdir() if os.path.isdir(a)]

Je pense que c'est le moyen le plus simple

2
KBLee

étant un débutant ici, je ne peux pas encore commenter directement, mais voici une petite correction que je voudrais ajouter à la partie suivante de réponse de ΤΖΩΤΖΙΟΥ :

Si vous préférez des chemins d'accès complets, utilisez cette fonction:

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

pour ceux qui sont toujours sur python <2.4 : la construction interne doit être une liste au lieu d'un tuple et doit donc lire comme ceci:

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

sinon, on obtient une erreur de syntaxe.

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

Pour une liste de noms de chemins complets, je préfère cette version à l'autre solutions ici:

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))]
1
Malius Arth
scanDir = "abc"
directories = [d for d in os.listdir(scanDir) if os.path.isdir(os.path.join(os.path.abspath(scanDir), d))]
1
nvd

Ainsi?

>>>> [path for path in os.listdir(os.getcwd()) if os.path.isdir(path)]
0
Kirk Strauser

Une option plus sûre qui n'échoue pas lorsqu'il n'y a pas de répertoire.

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
Alexey Gavrilov