Menu

Node.js path-Modul: path.join vs. path.resolve

Das path-Modul baut Dateipfade richtig für das Betriebssystem zusammen und nimmt sie auseinander. path.join fügt Segmente zusammen; path.resolve macht daraus einen absoluten Pfad, ausgehend vom aktuellen Ordner.

Diese Seite enthält ausführbare Editoren. Bearbeiten, ausführen und Ausgabe sofort sehen.

path.join() verbindet Pfadsegmente mit dem richtigen Trennzeichen und räumt .. und doppelte Schrägstriche auf, lässt das Ergebnis aber relativ, wenn du mit einem relativen Segment angefangen hast. path.resolve() macht dieselbe Arbeit von rechts nach links und gibt immer einen absoluten Pfad zurück: Es startet beim aktuellen Arbeitsverzeichnis, und jedes absolute Segment unterwegs beginnt den Pfad neu. Nimm join, um einen Pfad zu bauen, und resolve, wenn du einen absoluten brauchst.

Es hat users/ada/notes.txt ausgegeben, dann users/grace/todo.txt (das .. hat ada entfernt), dann /srv/app/public/index.html und src/lib/utils.js: Überzählige Schrägstriche und leere Segmente sind weg. join behandelt /public/ nie als Neuanfang; es ist einfach das nächste Segment.

path.join vs. path.resolve

Der Unterschied zeigt sich, wenn ein Segment mit / beginnt oder wenn das erste Segment relativ ist:

Mit /public in der Mitte hat join /srv/app/public/img erzeugt, während resolve alles davor verworfen und /public/img erzeugt hat; .. haben beide gleich behandelt. Die letzten beiden Zeilen zeigen, dass join public/index.html relativ gelassen hat, während resolve es absolut gemacht hat, indem es den aktuellen Ordner davorgesetzt hat.

path.joinpath.resolve
ErgebnisRelativ oder absolut, wie die EingabeImmer absolut
Ein Segment, das mit / beginntNur ein weiteres SegmentBeginnt den Pfad dort neu
StartpunktKeinerDas aktuelle Arbeitsverzeichnis
Ohne Argumente'.'Das aktuelle Arbeitsverzeichnis
Typischer EinsatzEinen Pfad aus Teilen bauenNutzereingaben oder Konfiguration in einen absoluten Pfad verwandeln

basename, dirname, extname und parse

Diese Funktionen nehmen einen Pfad auseinander. Sie schauen nur auf den String: Die Datei muss nicht existieren.

Es hat cat.final.jpg, cat.final, /home/ada/photos und .jpg ausgegeben: extname nimmt nur den Teil nach dem letzten Punkt. path.parse gibt alles auf einmal zurück (root, dir, base, ext, name), und path.format macht aus so einem Objekt wieder einen String.

__dirname und __filename

In einer CommonJS-Datei ist __dirname der absolute Pfad des Ordners, der die Datei enthält, und __filename die Datei selbst. Ein relativer Pfad wie 'data.json' ist relativ dazu, wo der Nutzer node gestartet hat, und das bricht, sobald jemand dein Skript aus einem anderen Ordner startet. Bau Pfade stattdessen aus __dirname:

Es hat config.json dark und index.js ausgegeben. Die vollständigen Pfade sind auf jedem Rechner anders, genau deshalb baust du sie mit path.join(__dirname, ...), statt sie abzutippen.

__dirname in ES-Modulen: import.meta.dirname

ES-Module haben kein __dirname; wer es benutzt, bekommt ReferenceError: __dirname is not defined in ES module scope. Seit Node.js 20.11 ersetzen import.meta.dirname und import.meta.filename sie:

Es hat index.js und data/users.json ausgegeben. In Node.js-Versionen vor 20.11 leitest du den Ordner aus der Modul-URL ab: path.dirname(fileURLToPath(import.meta.url)), mit fileURLToPath aus node:url.

Warum du Pfade nicht mit Strings zusammensetzt

'data' + '/' + file funktioniert unter macOS und Linux und scheitert dann unter Windows, wo das Trennzeichen \ ist, und es tut nichts gegen .., doppelte oder fehlende Schrägstriche. path nutzt die Regeln des Systems, auf dem es läuft. Das Windows-Ergebnis siehst du auf jedem Rechner mit path.win32:

const path = require('path');

path.posix.join('users', 'ada', 'notes.txt'); // 'users/ada/notes.txt'
path.win32.join('users', 'ada', 'notes.txt'); // 'users\\ada\\notes.txt'
path.sep;                                     // '/' on macOS and Linux, '\\' on Windows

Übergib das Ergebnis von path.join an fs.readFile, und derselbe Code liest die Datei auf jedem System.

Häufige Fehler

Erwarten, dass extname doppelte Endungen kennt. path.extname('archive.tar.gz') ist '.gz', und eine Dotfile wie .env hat gar keine Endung: path.extname('.env') ist ''. Prüf das Ende des Namens selbst, wenn die ganze Endung wichtig ist.

Sich darauf verlassen, dass join einen Nutzer in einem Ordner hält. path.join('/srv/app', '../../etc/passwd') ist '/etc/passwd'. Bevor du eine Datei liest, die eine Anfrage benennt, löse den Pfad auf und prüf, dass er noch mit deinem Ordner beginnt.

Häufig gestellte Fragen

Was ist der Unterschied zwischen __dirname und process.cwd()?

__dirname ist der Ordner der aktuellen Quelldatei und ändert sich nie. process.cwd() ist der Ordner, aus dem der Nutzer node gestartet hat. Gleich sind sie nur, wenn das Programm aus seinem eigenen Ordner gestartet wird.

Soll ich mit __dirname path.join oder path.resolve nehmen?

Für path.join(__dirname, 'data.json') geht beides, weil __dirname schon absolut ist. Nimm resolve, wenn ein Segment selbst absolut sein könnte, etwa ein vom Nutzer eingegebener Pfad, und dieser Pfad gewinnen soll.

Wie nutze ich das path-Modul mit URLs?

Gar nicht: URLs nutzen immer / und haben eigene Regeln für .. und Query-Strings. Nimm die Klasse URL, wie in new URL('../img/logo.png', 'https://example.com/docs/page').

Illustration der Programmiersprachen bei Coddy

Lerne mit Coddy zu programmieren

Los geht's