987 Stimmen

Abrufen einer Liste aller Unterverzeichnisse im aktuellen Verzeichnis

Gibt es eine Möglichkeit, eine Liste aller Unterverzeichnisse im aktuellen Verzeichnis in Python zurückzugeben?

Ich weiß, dass man das mit Dateien machen kann, aber ich muss stattdessen die Liste der Verzeichnisse bekommen.

950voto

Blair Conrad Punkte 217777

Meinen Sie unmittelbare Unterverzeichnisse oder jedes Verzeichnis ganz unten im Baum?

So oder so, Sie können Folgendes verwenden os.walk um dies zu tun:

os.walk(directory)

ergibt ein Tupel für jedes Unterverzeichnis. Der erste Eintrag in dem 3-Tupel ist ein Verzeichnisname, also

[x[0] for x in os.walk(directory)]

sollte Ihnen rekursiv alle Unterverzeichnisse anzeigen.

Beachten Sie, dass der zweite Eintrag im Tupel die Liste der untergeordneten Verzeichnisse des Eintrags an der ersten Position ist, so dass Sie dies stattdessen verwenden könnten, aber es ist nicht wahrscheinlich, dass Sie viel sparen.

Sie können aber auch nur die unmittelbaren Unterverzeichnisse angeben:

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

Oder sehen Sie sich die anderen bereits veröffentlichten Lösungen an, indem Sie os.listdir y os.path.isdir , einschließlich derjenigen unter " Wie man alle unmittelbaren Unterverzeichnisse in Python erhält ".

336voto

user136036 Punkte 8980

Viel schöner als das obige, weil Sie nicht mehrere os.path.join() brauchen und Sie direkt den vollständigen Pfad erhalten (wenn Sie wollen), können Sie dies tun in Python 3.5 und darüber.

subfolders = [ f.path for f in os.scandir(folder) if f.is_dir() ]

Dadurch wird der vollständige Pfad zum Unterverzeichnis angegeben. Wenn Sie nur den Namen des Unterverzeichnisses wollen, verwenden Sie f.name anstelle von f.path

https://docs.python.org/3/library/os.html#os.scandir


Leicht OT: Falls Sie etwas brauchen alle Unterordner rekursiv und/oder alle Dateien rekursiv sehen Sie sich diese Funktion an, die schneller ist als os.walk & glob und gibt eine Liste aller Unterordner sowie aller Dateien innerhalb dieser (Unter-)Unterordner zurück: https://stackoverflow.com/a/59803793/2441026

Falls Sie nur alle Unterordner rekursiv :

def fast_scandir(dirname):
    subfolders= [f.path for f in os.scandir(dirname) if f.is_dir()]
    for dirname in list(subfolders):
        subfolders.extend(fast_scandir(dirname))
    return subfolders

Gibt eine Liste aller Unterordner mit ihren vollständigen Pfaden zurück. Dies ist wiederum schneller als os.walk und viel schneller als glob .


Eine Analyse aller Funktionen

tl;dr:
- Wenn Sie alles bekommen möchten sofort Unterverzeichnisse für einen Ordner verwenden os.scandir .
- Wenn Sie sich alle Unterverzeichnisse, auch verschachtelt die, verwenden os.walk oder - etwas schneller - die fast_scandir Funktion oben.
- Verwenden Sie niemals os.walk nur für Unterverzeichnisse der obersten Ebene, da es hunderte(!) Mal langsamer sein kann als os.scandir .

  • Wenn Sie den nachstehenden Code ausführen, stellen Sie sicher, dass Sie ihn einmal ausführen, damit Ihr Betriebssystem auf den Ordner zugreifen kann, verwerfen Sie die Ergebnisse und führen Sie den Test aus.
  • Vielleicht möchten Sie die Funktionsaufrufe vertauschen, aber ich habe es getestet, und es war nicht wirklich wichtig.
  • In allen Beispielen wird der vollständige Pfad zum Ordner angegeben. Das pathlib Beispiel als (Windows)Path Objekt.
  • Das erste Element von os.walk wird der Basisordner sein. Sie werden also nicht nur Unterverzeichnisse erhalten. Sie können verwenden fu.pop(0) um sie zu entfernen.
  • Bei keinem der Ergebnisse wird eine natürliche Sortierung verwendet . Das bedeutet, dass die Ergebnisse wie folgt sortiert werden: 1, 10, 2. Um die natürliche Sortierung (1, 2, 10), sehen Sie bitte unter https://stackoverflow.com/a/48030307/2441026

Ergebnisse :

os.scandir      took   1 ms. Found dirs: 439
os.walk         took 463 ms. Found dirs: 441 -> it found the nested one + base folder.
glob.glob       took  20 ms. Found dirs: 439
pathlib.iterdir took  18 ms. Found dirs: 439
os.listdir      took  18 ms. Found dirs: 439

Getestet mit W7x64, Python 3.8.1.

# -*- coding: utf-8 -*-
# Python 3

import time
import os
from glob import glob
from pathlib import Path

directory = r"<insert_folder>"
RUNS = 1

def run_os_walk():
    a = time.time_ns()
    for i in range(RUNS):
        fu = [x[0] for x in os.walk(directory)]
    print(f"os.walk\t\t\ttook {(time.time_ns() - a) / 1000 / 1000 / RUNS:.0f} ms. Found dirs: {len(fu)}")

def run_glob():
    a = time.time_ns()
    for i in range(RUNS):
        fu = glob(directory + "/*/")
    print(f"glob.glob\t\ttook {(time.time_ns() - a) / 1000 / 1000 / RUNS:.0f} ms. Found dirs: {len(fu)}")

def run_pathlib_iterdir():
    a = time.time_ns()
    for i in range(RUNS):
        dirname = Path(directory)
        fu = [f for f in dirname.iterdir() if f.is_dir()]
    print(f"pathlib.iterdir\ttook {(time.time_ns() - a) / 1000 / 1000 / RUNS:.0f} ms. Found dirs: {len(fu)}")

def run_os_listdir():
    a = time.time_ns()
    for i in range(RUNS):
        dirname = Path(directory)
        fu = [os.path.join(directory, o) for o in os.listdir(directory) if os.path.isdir(os.path.join(directory, o))]
    print(f"os.listdir\t\ttook {(time.time_ns() - a) / 1000 / 1000 / RUNS:.0f} ms. Found dirs: {len(fu)}")

def run_os_scandir():
    a = time.time_ns()
    for i in range(RUNS):
        fu = [f.path for f in os.scandir(directory) if f.is_dir()]
    print(f"os.scandir\t\ttook {(time.time_ns() - a) / 1000 / 1000 / RUNS:.0f} ms.\tFound dirs: {len(fu)}")

if __name__ == '__main__':
    run_os_scandir()
    run_os_walk()
    run_glob()
    run_pathlib_iterdir()
    run_os_listdir()

331voto

Udit Bansal Punkte 2761

Sie könnten einfach Folgendes verwenden glob.glob

from glob import glob
glob("/path/to/directory/*/", recursive = True)

Vergessen Sie nicht den Nachsatz / nach dem * .

216voto

gahooa Punkte 121696
import os

d = '.'
[os.path.join(d, o) for o in os.listdir(d) 
                    if os.path.isdir(os.path.join(d,o))]

95voto

joelostblom Punkte 33814

Python 3.4 eingeführt el pathlib Modul in die Standardbibliothek aufgenommen, die einen objektorientierten Ansatz zur Behandlung von Dateisystempfaden bietet:

from pathlib import Path

p = Path('./')

# All subdirectories in the current directory, not recursive.
[f for f in p.iterdir() if f.is_dir()]

Um alle Unterverzeichnisse rekursiv aufzulisten, Pfad-Globbing kann mit der Option ** Muster.

# This will also include the current directory '.'
list(p.glob('**'))

Beachten Sie, dass eine einzelne * da das glob-Muster sowohl Dateien als auch Verzeichnisse nicht rekursiv einschließen würde. Um nur Verzeichnisse zu erhalten, muss ein nachgestellter / kann angehängt werden, aber das funktioniert nur, wenn die glob-Bibliothek direkt verwendet wird, nicht wenn glob über pathlib verwendet wird:

import glob

# These three lines return both files and directories
list(p.glob('*'))
list(p.glob('*/'))
glob.glob('*')

# Whereas this returns only directories
glob.glob('*/')

Also Path('./').glob('**') entspricht denselben Pfaden wie glob.glob('**/', recursive=True) .

Pathlib ist auch unter Python 2.7 verfügbar über das Modul pathlib2 auf PyPi.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X