Abschnitt 3 · Lektion 3
Verzeichnisse
Eine einzelne Datei zu lesen ist der einfache Fall. Meistens weißt du aber gar nicht, welche Dateien es gibt, sondern willst genau das erst herausfinden.
Einen Ordner auflesen
readdir gibt dir die Namen der Einträge in einem Verzeichnis.
Kaffee kaufen
Kurs bauen Notiz eins import { readdir } from "node:fs/promises";
// readdir garantiert keine Reihenfolge, deshalb wird hier sortiert.
const namen = (await readdir("inhalt")).sort();
console.log(namen);
console.log("Anzahl:", namen.length); Zwei Dinge fallen daran auf.
Es sind Namen, keine Pfade. In der Liste steht aufgaben.txt und nicht inhalt/aufgaben.txt.
Der Ordner, den du gerade abgefragt hast, taucht in den Ergebnissen nicht auf.
Die Reihenfolge ist nicht garantiert. Node reicht durch, was das Betriebssystem liefert, und das ist je nach Dateisystem die Reihenfolge des Anlegens, eine Hash-Reihenfolge oder etwas ganz anderes. Auf deinem Rechner sieht es oft sortiert aus, auf dem Server nicht. Wenn du eine Reihenfolge brauchst, sortier selbst. Das ist eine Zeile und erspart dir einen Fehler, der nur woanders auftritt.
Die Falle mit dem Namen
Jetzt der Fehler, den in Node fast jeder einmal macht.
Kaffee kaufen
Kurs bauen Notiz eins import { readdir, readFile } from "node:fs/promises";
const namen = (await readdir("inhalt")).sort();
console.log("Gefunden:", namen[1]);
// Gesucht wird im Arbeitsverzeichnis, nicht in inhalt/.
await readFile(namen[1], "utf8"); Der Name aus readdir ist relativ zu dem Ordner, den du aufgelesen hast. readFile löst ihn aber
gegen das Arbeitsverzeichnis auf, und dort liegt die Datei nicht. Ergebnis: ENOENT für eine
Datei, die du gerade selbst in der Liste gesehen hast. Im Terminal steht erst
Gefunden: notizen.txt und darunter in Rot ENOENT: no such file or directory, open 'notizen.txt',
und der Pfad in der Meldung sagt es schon: kein inhalt/ davor.
Das kannst du dir im Terminal ansehen, statt es zu glauben. ls zeigt, was im Arbeitsverzeichnis
liegt, nämlich index.mjs und den Ordner inhalt. ls inhalt zeigt, was darin liegt, nämlich die
beiden Textdateien. readFile sucht in der ersten Liste, gefunden hast du den Namen in der zweiten.
Die Lösung kennst du schon aus Lektion 2.4: path.join("inhalt", name). Genau dafür gibt es
node:path, und genau hier merkst du zum ersten Mal, warum.
Datei oder Ordner
readdir allein sagt dir nicht, was hinter einem Namen steckt. Dafür gibt es zwei Wege.
Der bequeme ist withFileTypes: true. Dann bekommst du statt Zeichenketten kleine Objekte, die ihren
Namen kennen und die Frage isDirectory() beantworten können.
Kaffee kaufen
Kurs bauen Alte Notiz import { readdir } from "node:fs/promises";
const eintraege = await readdir("inhalt", { withFileTypes: true });
eintraege.sort((a, b) => a.name.localeCompare(b.name));
for (const eintrag of eintraege) {
console.log(`${eintrag.name} (${eintrag.isDirectory() ? "Ordner" : "Datei"})`);
} In inhalt liegt neben der Textdatei ein Ordner archiv, und genau den unterscheidet das Beispiel:
archiv (Ordner) über aufgaben.txt (Datei).
Der allgemeine Weg ist stat(pfad). Es liefert deutlich mehr: Größe in Bytes, Zeitpunkt der letzten
Änderung, Rechte, und ebenfalls isDirectory() und isFile(). Dafür brauchst du einen richtigen
Pfad und einen Aufruf je Eintrag.
Faustregel: Willst du nur wissen, ob Datei oder Ordner, nimm withFileTypes. Willst du Größe oder
Datum, nimm stat.
Ordner anlegen
mkdir("berichte") legt einen Ordner an und scheitert, wenn es ihn schon gibt oder wenn der
übergeordnete Ordner fehlt.
Deshalb schreibt man in der Praxis fast immer mkdir("berichte/2026", { recursive: true }). Das legt
den ganzen Weg an, und, das ist der eigentliche Gewinn, es beschwert sich nicht, wenn schon alles da
ist. Damit kannst du es bei jedem Start aufrufen, ohne vorher zu prüfen.
Warum man vorher nicht prüft
Damit sind wir bei einer Gewohnheit, die in Node anders ist als anderswo. Es gibt zwar eine Funktion, die fragt, ob etwas existiert, aber man benutzt sie besser nicht.
Der Grund: Zwischen deiner Frage und deiner Handlung liegt ein Moment, und in diesem Moment kann sich die Welt ändern. Ein anderer Prozess löscht die Datei, ein Backup verschiebt sie, ein Benutzer räumt auf. Dein Code hat dann geprüft, dass alles in Ordnung ist, und stürzt eine Zeile später trotzdem ab.
Die Node-Denkweise ist deshalb: versuch es einfach und fang den Fehler ab. Das ist nicht nur sicherer, sondern auch kürzer. Wie das aussieht, kommt in der nächsten Lektion.
Zum Mitnehmen
readdir gibt dir Namen, keine Pfade. Wer einen Namen direkt an readFile weiterreicht, sucht im falschen Verzeichnis.
Jetzt du
Basis Konto, kostenlosZu 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 3 Beispielen zum Ausprobieren
Steht hier, ohne Konto lesbar.
-
Aufgabe, dein Code läuft auf einem Server
Öffnet sich mit dem Basis Konto.