Comment lister uniquement les répertoires de premier niveau en Python?
-
02-07-2019 - |
Question
Je souhaite pouvoir répertorier uniquement les répertoires 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. Ce que je veux fonctionne essentiellement 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.
La solution
Filtrez le résultat en utilisant os.path.isdir () (et utilisez os.path.join () pour obtenir le chemin réel):
>>> [ 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']
Autres conseils
os.walk
Utilisez 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
[1]
est un générateur et appeler dirnames
obtiendra le premier résultat sous la forme d'un tuple de 3 (dirpath, dirnames, noms de fichiers). Ainsi, <=> l'index ne renvoie que le <=> de ce tuple.
Filtrez la liste en utilisant os.path.isdir pour détecter les répertoires.
filter(os.path.isdir, os.listdir(os.getcwd()))
directories=[d for d in os.listdir(os.getcwd()) if os.path.isdir(d)]
Notez qu'au lieu de faire os.listdir(os.getcwd())
, il est préférable de le 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)
]
Juste pour ajouter que l'utilisation de os.listdir () ne & "prend pas beaucoup de traitement par rapport à une 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.
Une méthode 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 que celui pour lequel vous souhaitez attribuer un nom à un dossier. Il vous donnera exactement le nom du dossier immédiat uniquement (sans le chemin d'accès complet au dossier).
Cela semble fonctionner aussi (au moins sur Linux):
import glob, os
glob.glob('*' + os.path.sep)
é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 & # 932; & # 918; & # 937; & # 932; & # 918 ; & # 921; & # 927; la réponse de & # 933; :
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 se lire comme suit:
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.
En utilisant 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
[x for x in os.listdir(somedir) if os.path.isdir(os.path.join(somedir, x))]
Pour obtenir une liste des noms de chemin d'accès complets, je préfère cette version aux autres 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))]
scanDir = "abc"
directories = [d for d in os.listdir(scanDir) if os.path.isdir(os.path.join(os.path.abspath(scanDir), d))]
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 []
Aimez-vous?
>>>> [path for path in os.listdir(os.getcwd()) if os.path.isdir(path)]
-- 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