Wie liste ich nur Verzeichnisse der obersten Ebene in Python auf?

131

Ich möchte nur die Verzeichnisse in einem Ordner auflisten können. Dies bedeutet, dass ich weder Dateinamen noch zusätzliche Unterordner auflisten möchte.

Mal sehen, ob ein Beispiel hilft. Im aktuellen Verzeichnis haben wir:

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

Ich möchte jedoch nicht, dass Dateinamen aufgelistet werden. Ich möchte auch keine Unterordner wie \ Lib \ curses. Im Wesentlichen funktioniert das, was ich möchte, mit Folgendem:

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

Ich frage mich jedoch, ob es einen einfacheren Weg gibt, die gleichen Ergebnisse zu erzielen. Ich habe den Eindruck, dass die Verwendung von os.walk nur zur Rückgabe der obersten Ebene ineffizient / zu viel ist.

fuentesjr
quelle

Antworten:

124

Filtern Sie das Ergebnis mit os.path.isdir () (und verwenden Sie os.path.join (), um den tatsächlichen Pfad zu erhalten):

>>> [ 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']
Thomas Wouters
quelle
17
Dies erfordert viel Verarbeitung im Vergleich zu sehr einfachen os.walk (). Next () [1]
Phyo Arkar Lwin
201

os.walk

Verwendung os.walkmit nextItem-Funktion:

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

Für Python <= 2.5 verwenden Sie:

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

Wie das funktioniert

os.walkist ein Generator und der Aufruf nexterhält das erste Ergebnis in Form eines 3-Tupels (dirpath, dirnames, filenames). Somit gibt der [1]Index nur das dirnamesvon diesem Tupel zurück.

Alex Coventry
quelle
14
Ein wenig mehr Beschreibung dazu ist, dass dies ein Generator ist, es wird nicht die anderen dirs laufen, es sei denn, Sie sagen es. Also macht .next () [1] in einer Zeile das, was alle Listenverständnisse tun. Ich würde wahrscheinlich so etwas tun DIRNAMES=1und es dann next()[DIRNAMES]für zukünftige Code-Betreuer verständlicher machen.
Bootscodierer
3
+1 erstaunliche Lösung. Um ein Verzeichnis zum Durchsuchen anzugeben, verwenden Sie:os.walk( os.path.join(mypath,'.')).next()[1]
Daniel Reis
42
für Python v3: next (os.walk ('.')) [1]
Andre Soares
Wenn Sie mehr tun wollen als Textverarbeitung. dh die Verarbeitung in den tatsächlichen Ordnern, dann können vollständige Pfade erforderlich sein:sorted( [os.path.join(os.getcwd(), item) for item in os.walk(os.curdir).next()[1]] )
DevPlayer
52

Filtern Sie die Liste mit os.path.isdir, um Verzeichnisse zu erkennen.

filter(os.path.isdir, os.listdir(os.getcwd()))
Colin Jensen
quelle
5
Ich denke, dies ist bei weitem die beste Kombination aus Lesbarkeit und Prägnanz in einer dieser Antworten.
Vergenzt
20
Das hat nicht funktioniert. Ich vermute, dass os.listdirein Datei- / Ordnername zurückgegeben wird, an den weitergegeben os.path.isdirwird, letzterer jedoch einen vollständigen Pfad benötigt.
Daniel Reis
3
Filter ist schneller als os.walk timeit(os.walk(os.getcwd()).next()[1]) 1000 loops, best of 3: 734 µs per loop timeit(filter(os.path.isdir, os.listdir(os.getcwd()))) 1000 loops, best of 3: 477 µs per loop
B.Kocis
14
directories=[d for d in os.listdir(os.getcwd()) if os.path.isdir(d)]
Mark Roddy
quelle
4
Dies kann gekürzt werden, um zu filtern (os.path.isdir, os.listdir (os.getcwd ())
John Millikin
3
Hat jemand Informationen darüber, ob Filter oder Listenverständnis schneller sind? Ansonsten ist es nur ein subjektives Argument. Dies setzt natürlich voraus, dass sich 10 Millionen Verzeichnisse im cwd befinden und die Leistung ein Problem darstellt.
Mark Roddy
12

Beachten Sie, dass dies os.listdir(os.getcwd())vorzuziehen ist os.listdir(os.path.curdir). Ein Funktionsaufruf weniger, und es ist genauso portabel.

Um die Antwort zu vervollständigen und eine Liste der Verzeichnisse in einem Ordner zu erhalten:

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

Wenn Sie vollständige Pfadnamen bevorzugen, verwenden Sie diese Funktion:

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

Dies scheint auch zu funktionieren (zumindest unter Linux):

import glob, os
glob.glob('*' + os.path.sep)
Travis
quelle
1
+1 für glob. Es kann Ihnen viel Code sparen, insbesondere Iterationen, und ist der Verwendung von UNIX-Terminals sehr ähnlich ( ls)
Gerard
5
Anstelle von glob.glob ('*' + os.path.sep) möchten Sie vielleicht [dir für dir in glob.glob ("*") schreiben, wenn os.path.isdir (dir)]
Eamonn MR
8

Nur um hinzuzufügen, dass die Verwendung von os.listdir () nicht "viel Verarbeitung im Vergleich zu sehr einfachem os.walk (). Next () [1] erfordert" . Dies liegt daran, dass os.walk () os.listdir () intern verwendet. In der Tat, wenn Sie sie zusammen testen:

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

Das Filtern von os.listdir () ist etwas schneller.

foz
quelle
2
Mit Python 3.5 können Sie schneller Verzeichnisinhalte abrufen
foz
1
pep-0471 - das scandirPaket - ist ab Python 2.6 als installierbares Paket auf PyPI verfügbar. Es bietet Ersatz für os.walkund os.listdirdas ist viel schneller.
Foz
6

Eine sehr viel einfachere und elegantere Möglichkeit besteht darin, Folgendes zu verwenden:

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

Führen Sie dieses Skript in demselben Ordner aus, für den Sie Ordnernamen möchten. Es gibt Ihnen nur genau den Namen des unmittelbaren Ordners (auch dies ohne den vollständigen Pfad der Ordner).

Manty
quelle
6

Listenverständnis verwenden,

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

Ich denke, es ist der einfachste Weg

KBLee
quelle
2

Da ich hier ein Neuling bin, kann ich noch keinen direkten Kommentar abgeben, aber hier ist eine kleine Korrektur, die ich dem folgenden Teil der Antwort von ΤΖΩΤΖΙΟΥ hinzufügen möchte :

Wenn Sie vollständige Pfadnamen bevorzugen, verwenden Sie diese Funktion:

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

für diejenigen, die noch auf Python <2.4 sind : Das innere Konstrukt muss eine Liste anstelle eines Tupels sein und sollte daher folgendermaßen lauten:

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

Andernfalls wird ein Syntaxfehler angezeigt.

Antiplex
quelle
Ich weiß, es ist schon eine Weile her, aber dieses erste Beispiel hat mir wirklich geholfen.
Inbar Rose
1
Sie erhalten einen Syntaxfehler, weil Ihre Version keine Generatorausdrücke unterstützt. Diese wurden in Python 2.4 eingeführt, während Listenverständnisse seit Python 2.0 verfügbar sind.
Awatts
1
[x for x in os.listdir(somedir) if os.path.isdir(os.path.join(somedir, x))]
Moe
quelle
1

Für eine Liste der vollständigen Pfadnamen ziehe ich diese Version den anderen Lösungen hier vor:

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

Eine sicherere Option, die nicht fehlschlägt, wenn kein Verzeichnis vorhanden ist.

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 []
Alexey Gavrilov
quelle
0

Wie so?

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

Python 3.4 führte das pathlibModul in die Standardbibliothek ein, die einen objektorientierten Ansatz für die Verarbeitung von Dateisystempfaden bietet:

from pathlib import Path

p = Path('./')
[f for f in p.iterdir() if f.is_dir()]
joelostblom
quelle
-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
venkata maddineni
quelle