Abrufen einer Liste aller Unterverzeichnisse im aktuellen Verzeichnis

Antworten:

603

Meinen Sie unmittelbare Unterverzeichnisse oder jedes Verzeichnis direkt im Baum?

In beiden Fällen können Sie Folgendes os.walktun:

os.walk(directory)

gibt für jedes Unterverzeichnis ein Tupel aus. Dieser erste Eintrag im 3-Tupel ist also ein Verzeichnisname

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

sollte Ihnen alle Unterverzeichnisse rekursiv geben.

Beachten Sie, dass der zweite Eintrag im Tupel die Liste der untergeordneten Verzeichnisse des Eintrags an der ersten Position ist. Sie können ihn also stattdessen verwenden, aber es ist unwahrscheinlich, dass Sie viel sparen.

Sie können es jedoch nur verwenden, um Ihnen die unmittelbaren untergeordneten Verzeichnisse zu geben:

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

Oder sehen Sie sich die anderen bereits veröffentlichten Lösungen an, die os.listdirund verwenden os.path.isdir, einschließlich der unter " So erhalten Sie alle unmittelbaren Unterverzeichnisse in Python ".

Blair Conrad
quelle
7
Ich denke, os.walk gibt Tripel zurück (root, dirs, files). Das bedeutet, dass dirs viele sich wiederholende Einträge hat. Gibt es einen effizienteren Weg, der durch Verzeichnisse rekursiv ist?
Mathtick
22
Nicht verwenden os.walk('.').next()[1]oder os.walk('.').__next__()[1]direkt. Verwenden Sie stattdessen die integrierte Funktion next(), die sowohl in Python 2 (siehe Dokument) als auch in Python 3 (siehe Dokument) verfügbar ist . Zum Beispiel : next(os.walk('.'))[1].
Lucio Paiva
1
@ Lucio Warum ist es schlecht, os.walk('.').next()[1]direkt zu verwenden ?
wisbucky
8
@wisbucky es ist eine schlechte Praxis, da iteraror.__next__()es sich um eine interne Methode handelt und die iterator.next()Verwendung next()gemäß PEP-3114 auf die integrierte Methode umgestellt werden sollte . Siehe PEP-3114, das 2007 genehmigt wurde.
Lucio Paiva
16
Für alle, die sich Gedanken über Leistungsunterschiede zwischen os.walkund os.listdir+ os.path.isdirLösungen machen: Ich habe gerade in einem Verzeichnis mit 10.000 Unterverzeichnissen (mit Millionen von Dateien in der folgenden Hierarchie) getestet, und die Leistungsunterschiede sind vernachlässigbar. os.walk: "10 Schleifen, am besten 3: 44,6 ms pro Schleife" und os.listdir+ os.path.isdir: "10 Schleifen, am besten 3: 45,1 ms pro Schleife"
Kevinmicke
165
import os

d = '.'
[os.path.join(d, o) for o in os.listdir(d) 
                    if os.path.isdir(os.path.join(d,o))]
gahooa
quelle
5
Beachten Sie, dass Sie sich bei diesem Ansatz um Abspath-Probleme kümmern müssen, wenn diese nicht auf '.' ausgeführt werden.
Daspostloch
4
Nur ein Kopf hoch, wenn Sie das cwd ('.') Nicht verwenden, funktioniert dies nur, wenn Sie einen os.path.joinOn ausführen o, um den vollständigen Pfad zu erhalten. Andernfalls isdir(0)wird immer false zurückgegeben
James McMahon
5
Es scheint, dass der Beitrag mit Korrekturen für die beiden oben genannten Probleme aktualisiert wurde.
CGMB
1
Um nicht os.path.joinzweimal os.path.isdirfilter(os.path.isdir, [os.path.join(d, o) for o in os.listdir(d)])
anzurufen
155

Sie könnten einfach verwenden glob.glob

from glob import glob
glob("/path/to/directory/*/")

Vergessen Sie nicht das Nachlaufen /nach dem *.

Udit Bansal
quelle
Nett. Einfach. Nur, es lässt die /
Spuren
9
Wenn Sie nicht davon ausgehen können /, der glob(os.path.join(path_to_directory, "*", ""))
Ordnertrenner
1
Dies funktioniert nicht für Unterverzeichnisse! Um glob zu verwenden, ist hier die vollständige Antwort: Verwenden Sie einen Glob (), um Dateien rekursiv in Python zu finden?
Mohn
1
Um Glob rekursiv zu machen, können Sie einfach das folgende Argument hinzufügenrecursive=True
JacoSolari
102

Viel schöner als die oben genannten, da Sie nicht mehrere os.path.join () benötigen und den vollständigen Pfad direkt erhalten (wenn Sie dies wünschen), können Sie dies in Python 3.5 und höher tun .

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 möchten, verwenden Sie f.namestattdessenf.path

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


Etwas OT: Wenn Sie alle Unterordner rekursiv und / oder alle Dateien rekursiv benötigen , sehen Sie sich diese Funktion an, die schneller als os.walk& ist globund eine Liste aller Unterordner sowie aller Dateien in diesen (Unter-) Unterordnern zurückgibt: https://stackoverflow.com/a/59803793/2441026

Falls Sie nur alle Unterordner rekursiv möchten :

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 wieder schneller als os.walkund viel schneller als glob.


Eine Analyse aller Funktionen

tl; dr:
- Wenn Sie alle unmittelbaren Unterverzeichnisse für einen Ordner abrufen möchten, verwenden Sie os.scandir.
- Wenn Sie alle Unterverzeichnisse abrufen möchten , auch verschachtelte , verwenden Sie os.walkdie fast_scandirobige Funktion oder - etwas schneller - .
- Niemals os.walknur für Unterverzeichnisse der obersten Ebene verwenden, da dies hunderte (!) Mal langsamer sein kann als os.scandir.

  • Wenn Sie den folgenden Code ausführen, stellen Sie sicher, dass Sie ihn einmal ausführen, damit Ihr Betriebssystem auf den Ordner zugegriffen hat, verwerfen Sie die Ergebnisse und führen Sie den Test aus. Andernfalls werden die Ergebnisse verschraubt.
  • Vielleicht möchten Sie die Funktionsaufrufe verwechseln, aber ich habe es getestet, und es war nicht wirklich wichtig.
  • Alle Beispiele geben den vollständigen Pfad zum Ordner an. Das pathlib-Beispiel als (Windows-) Pfadobjekt.
  • Das erste Element von os.walkwird der Basisordner sein. Sie erhalten also nicht nur Unterverzeichnisse. Sie können es verwenden fu.pop(0), um es zu entfernen.
  • Keines der Ergebnisse verwendet eine natürliche Sortierung . Dies bedeutet, dass die Ergebnisse wie folgt sortiert werden: 1, 10, 2. Um eine natürliche Sortierung (1, 2, 10) zu erhalten, besuchen Sie bitte 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()
user136036
quelle
35

Wenn Sie eine rekursive Lösung benötigen, die alle Unterverzeichnisse in den Unterverzeichnissen findet, verwenden Sie walk wie zuvor vorgeschlagen.

Wenn Sie nur die untergeordneten Verzeichnisse des aktuellen Verzeichnisses benötigen, kombinieren Sie os.listdirmitos.path.isdir

Eli Bendersky
quelle
23

Implementiert dies mit Python-Os-Walk. ( http://www.pythonforbeginners.com/code-snippets-source-code/python-os-walk/ )

import os

print("root prints out directories only from what you specified")
print("dirs prints out sub-directories from root")
print("files prints out all files from root and directories")
print("*" * 20)

for root, dirs, files in os.walk("/var/log"):
    print(root)
    print(dirs)
    print(files)
Charith De Silva
quelle
19

Sie können die Liste der Unterverzeichnisse (und Dateien) in Python 2.7 mit os.listdir (Pfad) abrufen.

import os
os.listdir(path)  # list of subdirectories and files
Oscar Martin
quelle
59
Dies schließt auch Dateien ein.
Tarnay Kálmán
2
Der Name ist verwirrend, da sich 'dir' nicht auf die Objekte bezieht, die die Liste bilden, sondern auf das Containerverzeichnis. Bitte überprüfen Sie Ihre einzeiligen Antworten. Für Anfänger ist es sehr verlockend, sie auszuwählen.
Titou
4
Beachten Sie, dass der os.listdirInhalt des Verzeichnisses einschließlich der Dateien aufgelistet ist.
Guneysus
13

Nur Verzeichnisse auflisten

print("\nWe are listing out only the directories in current directory -")
directories_in_curdir = filter(os.path.isdir, os.listdir(os.curdir))
print(directories_in_curdir)

Nur Dateien im aktuellen Verzeichnis auflisten

files = filter(os.path.isfile, os.listdir(os.curdir))
print("\nThe following are the list of all files in the current directory -")
print(files)
NutJobb
quelle
2
Funktionierte nicht unter Mac OS. Ich denke, dass das Problem darin besteht, dass os.listdir nur den Namen des Verzeichnisses und nicht den vollständigen Pfad zurückgibt, aber os.path.isdir nur True zurückgibt, wenn der vollständige Pfad ein Verzeichnis ist.
Derson
Dies funktioniert außerhalb des aktuellen Verzeichnisses, wenn Sie die Zeile geringfügig ändern: subdirs = filter (os.path.isdir, [os.path.join (dir, x) für x in os.listdir (dir)])
RLC
12

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('./')

# List comprehension
[f for f in p.iterdir() if f.is_dir()]

# The trailing slash to glob indicated directories
# This will also include the current directory '.'
list(p.glob('**/'))

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

joelostblom
quelle
Um die Liste der Unterverzeichnisse zu durchlaufen, ist hier eine schöne, saubere Syntax:for f in filter(Path.is_dir, p.iterdir()):
Bryan Roach
11

Da ich bei der Verwendung von Python 3.4- und Windows UNC-Pfaden auf dieses Problem gestoßen bin, gibt es hier eine Variante für diese Umgebung:

from pathlib import WindowsPath

def SubDirPath (d):
    return [f for f in d.iterdir() if f.is_dir()]

subdirs = SubDirPath(WindowsPath(r'\\file01.acme.local\home$'))
print(subdirs)

Pathlib ist neu in Python 3.4 und erleichtert die Arbeit mit Pfaden unter verschiedenen Betriebssystemen erheblich: https://docs.python.org/3.4/library/pathlib.html

Marcus Schommler
quelle
10

Obwohl diese Frage schon vor langer Zeit beantwortet wurde. Ich möchte empfehlen, die zu verwendenpathlib Modul zu verwenden, da dies eine robuste Methode ist, um unter Windows und Unix zu arbeiten.

So rufen Sie alle Pfade in einem bestimmten Verzeichnis ab, einschließlich der Unterverzeichnisse:

from pathlib import Path
paths = list(Path('myhomefolder', 'folder').glob('**/*.txt'))

# all sorts of operations
file = paths[0]
file.name
file.stem
file.parent
file.suffix

usw.

Joost Döbken
quelle
9

Danke für die Tipps, Leute. Ich bin auf ein Problem gestoßen, bei dem Softlinks (unendliche Rekursion) als Verzeichnisse zurückgegeben wurden. Softlinks? Wir wollen keine stinkenden Softlinks! Damit...

Dadurch wurden nur die Verzeichnisse und keine Softlinks gerendert:

>>> import os
>>> inf = os.walk('.')
>>> [x[0] for x in inf]
['.', './iamadir']
KurtB
quelle
1
Wie [x[0] for x in inf]heißt Python, damit ich es nachschlagen kann?
Shinzou
2
@shinzou Das ist ein Listenverständnis. Super nützlich. Schlagen Sie auch das Diktatverständnis nach.
KurtB
9

Kopieren Einfügen freundlich in ipython:

import os
d='.'
folders = list(filter(lambda x: os.path.isdir(os.path.join(d, x)), os.listdir(d)))

Ausgabe von print(folders):

['folderA', 'folderB']
Andrew Schreiber
quelle
2
Was ist X in diesem Fall?
Abhishek Parikh
1
@AbhishekParikh xist das Element aus der Liste, das von erstellt wurde, os.listdir(d)weil listdirDateien und Ordner zurückgegeben werden, mit denen er den filterBefehl verwendet os.path.isdir, um alle Dateien aus der Liste herauszufiltern.
James Burke
8

So mache ich es.

    import os
    for x in os.listdir(os.getcwd()):
        if os.path.isdir(x):
            print(x)
Mujeeb Ishaque
quelle
Es funktioniert nicht. Ich denke, in x müssen Sie einen vollständigen Pfad angeben, um dies mit isdir ()
niranjan patidar
Sie haben wahrscheinlich Probleme mit os.getcwd (); Im Wesentlichen können Sie den absoluten Pfad ermitteln und diesen stattdessen verwenden. dir = os.path.dirname (os.path.abspath ( Datei ))
Mujeeb Ishaque
mit os hat pat.join () für mich gearbeitet. Weil es geholfen hat, den vollständigen Pfad des Unterverzeichnisses zu erhalten.
Niranjan Patidar
7

Hier sind einige einfache Funktionen, die auf dem Beispiel von @Blair Conrad basieren:

import os

def get_subdirs(dir):
    "Get a list of immediate subdirectories"
    return next(os.walk(dir))[1]

def get_subfiles(dir):
    "Get a list of immediate subfiles"
    return next(os.walk(dir))[2]
Brian Burns
quelle
6

Verwenden Sie das folgende Beispiel, um auf der Lösung von Eli Bendersky aufzubauen:

import os
test_directory = <your_directory>
for child in os.listdir(test_directory):
    test_path = os.path.join(test_directory, child)
    if os.path.isdir(test_path):
        print test_path
        # Do stuff to the directory "test_path"

Wo <your_directory>ist der Pfad zu dem Verzeichnis, das Sie durchlaufen möchten?

Blairg23
quelle
5

Mit vollständigem Pfad und einen Anteil von Pfad Wesen ., .., \\, ..\\..\\subfolder, etc:

import os, pprint
pprint.pprint([os.path.join(os.path.abspath(path), x[0]) \
    for x in os.walk(os.path.abspath(path))])
DevPlayer
quelle
4

Diese Antwort schien noch nicht zu existieren.

directories = [ x for x in os.listdir('.') if os.path.isdir(x) ]
Andy
quelle
7
Dies gibt immer eine leere Liste zurück, wenn Sie etwas anderes als das aktuelle Arbeitsverzeichnis suchen. Dies ist technisch gesehen das Ziel des OP, aber nicht sehr wiederverwendbar.
Ochawkeye
2
Verzeichnisse = [x für x in os.listdir (localDir) wenn os.path.isdir (localDir + x)
Poonam
3

Ich hatte kürzlich eine ähnliche Frage und fand heraus, dass die beste Antwort für Python 3.6 (wie Benutzer Havlock hinzugefügt hat) die Verwendung ist os.scandir. Da es anscheinend keine Lösung gibt, werde ich meine eigene hinzufügen. Erstens eine nicht rekursive Lösung, die nur die Unterverzeichnisse direkt unter dem Stammverzeichnis auflistet.

def get_dirlist(rootdir):

    dirlist = []

    with os.scandir(rootdir) as rit:
        for entry in rit:
            if not entry.name.startswith('.') and entry.is_dir():
                dirlist.append(entry.path)

    dirlist.sort() # Optional, in case you want sorted directory names
    return dirlist

Die rekursive Version würde folgendermaßen aussehen:

def get_dirlist(rootdir):

    dirlist = []

    with os.scandir(rootdir) as rit:
        for entry in rit:
            if not entry.name.startswith('.') and entry.is_dir():
                dirlist.append(entry.path)
                dirlist += get_dirlist(entry.path)

    dirlist.sort() # Optional, in case you want sorted directory names
    return dirlist

Denken Sie daran, dass dies entry.pathden absoluten Pfad zum Unterverzeichnis darstellt. Falls Sie nur den Ordnernamen benötigen, können Sie entry.namestattdessen verwenden. Weitere Informationen zum Objekt finden Sie unter os.DirEntryentry .

Alberto A.
quelle
Tatsächlich funktioniert die Art und Weise, wie dies geschrieben ist, nicht mit 3.5, sondern nur mit 3.6. Um auf 3.5 zu verwenden, müssen Sie den Kontextmanager entfernen - siehe stackoverflow.com/questions/41401417/…
havlock
Das ist richtig. Ich könnte schwören, dass ich irgendwo gelesen habe, dass der Kontextmanager in 3.5 implementiert wurde, aber es scheint, dass ich falsch liege.
Alberto A
1

Verwenden Sie eine Filterfunktion os.path.isdirfür so os.listdir() etwasfilter(os.path.isdir,[os.path.join(os.path.abspath('PATH'),p) for p in os.listdir('PATH/')])

oneLeggedChicken
quelle
1

Dadurch werden alle Unterverzeichnisse direkt im Dateibaum aufgelistet.

import pathlib


def list_dir(dir):
    path = pathlib.Path(dir)
    dir = []
    try:
        for item in path.iterdir():
            if item.is_dir():
                dir.append(item)
                dir = dir + list_dir(item)
        return dir
    except FileNotFoundError:
        print('Invalid directory')

pathlib ist neu in Version 3.4

Yossarian42
quelle
1

Funktion zum Zurückgeben einer Liste aller Unterverzeichnisse innerhalb eines bestimmten Dateipfads. Durchsucht den gesamten Dateibaum.

import os

def get_sub_directory_paths(start_directory, sub_directories):
    """
    This method iterates through all subdirectory paths of a given 
    directory to collect all directory paths.

    :param start_directory: The starting directory path.
    :param sub_directories: A List that all subdirectory paths will be 
        stored to.
    :return: A List of all sub-directory paths.
    """

    for item in os.listdir(start_directory):
        full_path = os.path.join(start_directory, item)

        if os.path.isdir(full_path):
            sub_directories.append(full_path)

            # Recursive call to search through all subdirectories.
            get_sub_directory_paths(full_path, sub_directories)

return sub_directories
Matthew Ashley
quelle
1

Mit os.walk () können wir eine Liste aller Ordner abrufen.

import os

path = os.getcwd()

pathObject = os.walk(path)

Dieses pathObject ist ein Objekt und wir können ein Array von erhalten

arr = [x for x in pathObject]

arr is of type [('current directory', [array of folder in current directory], [files in current directory]),('subdirectory', [array of folder in subdirectory], [files in subdirectory]) ....]

Wir können eine Liste aller Unterverzeichnisse erhalten, indem wir das arr durchlaufen und das mittlere Array drucken

for i in arr:
   for j in i[1]:
      print(j)

Dadurch wird das gesamte Unterverzeichnis gedruckt.

So erhalten Sie alle Dateien:

for i in arr:
   for j in i[2]:
      print(i[0] + "/" + j)
Shivam Kesarwani
quelle
0

Diese Funktion mit einem bestimmten übergeordneten directoryElement durchläuft alle directoriesrekursiven Funktionen und printsalle filenamesdarin enthaltenen Elemente. Zu nützlich.

import os

def printDirectoryFiles(directory):
   for filename in os.listdir(directory):  
        full_path=os.path.join(directory, filename)
        if not os.path.isdir(full_path): 
            print( full_path + "\n")


def checkFolders(directory):

    dir_list = next(os.walk(directory))[1]

    #print(dir_list)

    for dir in dir_list:           
        print(dir)
        checkFolders(directory +"/"+ dir) 

    printDirectoryFiles(directory)       

main_dir="C:/Users/S0082448/Desktop/carpeta1"

checkFolders(main_dir)


input("Press enter to exit ;")
dbz
quelle
0

Durch die Verbindung mehrerer Lösungen von hier aus habe ich Folgendes verwendet:

import os
import glob

def list_dirs(path):
    return [os.path.basename(x) for x in filter(
        os.path.isdir, glob.glob(os.path.join(path, '*')))]
SadSeven
quelle