mitmario.dev

Ordner durchsuchen

Python Sandbox 3 Min Lesezeit 5 BeispieleLektion 5 von 8

Bevor ein Programm Dateien aufräumen kann, muss es erst einmal wissen, welche es gibt. Bisher stand jeder Dateiname fest im Code. Ein Download-Ordner ändert sich aber jeden Tag, und vor jedem Lauf eine Liste abtippen will niemand. Also fragt das Programm den Ordner selbst.

Was in einem Ordner liegt

Was in einem Ordner liegt
from pathlib import Path

for eintrag in sorted(Path("fotos").iterdir()):
    if eintrag.is_dir():
        print(eintrag, "(Ordner)")
    else:
        print(eintrag)

iterdir() (iterate directory, den Ordner durchgehen) liefert alles, was direkt im Ordner liegt, Dateien und Unterordner, jeweils als Path. Was im Unterordner 2025 liegt, kommt nicht vor. Ob ein Eintrag ein Ordner ist, sagt is_dir() aus der letzten Lektion.

Vor der Schleife steht sorted(), und das hat einen Grund. In welcher Reihenfolge die Einträge kommen, legt nicht Python fest, sondern das Dateisystem. Auf deinem Rechner kann sie anders sein als hier. Und auf demselben Rechner auch, nachdem der Ordner woandershin kopiert wurde. Ohne sorted() sieht die Ausgabe heute richtig aus und morgen anders.

Sortiert wird dabei nach dem Pfad. Auf Linux und dem Mac geht das Zeichen für Zeichen, also Ziffern vor Großbuchstaben vor Kleinbuchstaben. Unter Windows werden Pfade ohne Rücksicht auf Groß und Klein sortiert.

Nur bestimmte Dateien

Nur bestimmte Dateien
from pathlib import Path

for bild in sorted(Path("fotos").glob("*.jpg")):
    print(bild)

glob("*.jpg") liefert nur, was auf ein Muster passt. Der Stern steht für beliebig viele beliebige Zeichen. *.jpg heißt also irgendein Name, der auf .jpg endet. Das Wort glob ist ein altes Kürzel aus der Unix-Welt für genau diese Muster. Auch mit glob wird nur im Ordner selbst gesucht, und der Hafen im Unterordner fehlt.

Auch in Unterordnern

Auch in Unterordnern
from pathlib import Path

for bild in sorted(Path("fotos").rglob("*.jpg")):
    print(bild)
print(len(list(Path("fotos").rglob("*"))), "Einträge insgesamt")

rglob ist dasselbe, nur rekursiv (recursive). Es geht in jeden Unterordner und auch in die Unterordner der Unterordner, so tief es eben geht. Jetzt ist der Hafen dabei, mit seinem Pfad fotos/2025/hafen.jpg. Mit dem Muster "*" liefert rglob alles, was es gibt, Dateien und Ordner zusammen. In der letzten Zeile stehen deshalb vier Dateien und ein Ordner.

Wie groß eine Datei ist

Wie groß eine Datei ist
from pathlib import Path

notizen = Path("fotos/notizen.txt")
print(notizen.stat().st_size, "Bytes")
print(len(notizen.read_text(encoding="utf-8")), "Zeichen")

stat() fragt das Dateisystem nach allem, was es über eine Datei weiß, und st_size ist die Größe in Bytes. Die Datei hat ein Byte mehr, als ihr Text Zeichen hat. Das ü ist ein Zeichen, braucht in UTF-8 aber zwei Bytes (Lektion 11.2).

Wenn du die Größe über len() des Inhalts ausrechnest, zählst du Zeichen und liegst bei jedem Umlaut daneben. Außerdem musst du dafür die ganze Datei lesen, und bei einem Video von vier Gigabyte dauert das.

Ein Ordner hat auch eine Größe
from pathlib import Path

summe = 0
for eintrag in sorted(Path("fotos").rglob("*")):
    print(eintrag, eintrag.stat().st_size)
    summe += eintrag.stat().st_size
print("Zusammen:", summe, "Bytes")

rglob("*") liefert auch den Ordner 2025, und der hat ebenfalls eine Größe. Über seinen Inhalt sagt sie aber nichts. Es ist der Platz, den sein Verzeichnis selbst belegt. Je nach Dateisystem steht dort eine Zahl wie 4096 oder nur ein paar Byte, und wenn sie mitgezählt wird, stimmt die Summe so oder so nicht mehr. Wer nur Dateien zählen will, fragt vor dem Addieren is_file().

Gesucht wird in den Beispielen und in der Aufgabe übrigens in einem eigenen Ordner wie fotos oder daten, nie im Arbeitsverzeichnis selbst. Dort liegt auch main.py. Ein Programm, das die eigenen Dateien mitzählt, gibt jedes Mal eine andere Antwort, sobald du eine Datei anlegst.

Was die Aufgabe will

Aus einer alten Notiz-App sind die Notizen als Textdateien exportiert, in Ordnern nach Jahren, und dazwischen liegt anderes Zeug. Gesucht sind alle Textdateien samt Größe, die größte zuerst. Darunter soll stehen, wie viel es zusammen ist.

Zum Mitnehmen

iterdir() geht einen Ordner ohne seine Unterordner durch. Mit glob("*.jpg") kommt nur, was auf das Muster passt, und rglob("*.jpg") sucht auch in allen Unterordnern. Weil die Reihenfolge am Dateisystem hängt, kommt sorted() davor. Wie viele Bytes eine Datei belegt, steht in stat().st_size.

Jetzt du

Basis Konto, kostenlos

Zu dieser Lektion gehört eine Aufgabe. Du schreibst den Code selbst, und nach jedem Lauf sagt dir eine Prüfliste, was schon stimmt.

Dafür brauchst du das Basis Konto. Es kostet nichts, und ein Passwort gibt es auch nicht.

In diesem Kurs läuft dein Code auf einem Server. Dafür hat das Basis Konto 1 Stunde im Monat, mehr Zeit gibt es mit dem Premium Konto.

Was in dieser Lektion steckt

  • Artikel mit 5 Beispielen zum Ausprobieren

    Steht hier, ohne Konto lesbar.

  • Aufgabe, dein Code läuft auf einem Server

    Öffnet sich mit dem Basis Konto.