Was ist der Unterschied zwischen __dirname und ./ in node.js?


498

Gibt es beim Programmieren in Node.js und beim Verweisen auf Dateien, die sich irgendwo in Bezug auf Ihr aktuelles Verzeichnis befinden, einen Grund, die __dirnameVariable anstelle einer regulären zu verwenden ./? Ich habe bisher ./ in meinem Code verwendet und gerade die Existenz von ./ entdeckt __dirnameund möchte im Wesentlichen wissen, ob es klug wäre, meine ./s in diese umzuwandeln, und wenn ja, warum das eine kluge Idee wäre .


47
tl; dr: Grundsätzlich besteht der Unterschied darin, dass sich './' und 'process.cwd ()' auf das aktuelle Verzeichnis des Terminals beziehen, das das Skript aufruft, während sich '__dirname' auf das Verzeichnis bezieht, in dem sich das Skript befindet gelagert.
Gui Imamura

1
Außer wenn .es im Inneren verwendet wird require. Der Pfad darin requireist immer relativ zu der Datei, die den Aufruf von enthält require.
Govind Rai

Antworten:


814

Das Wesentliche

In Node.js __dirnamebefindet sich immer das Verzeichnis, in dem sich das aktuell ausgeführte Skript befindet ( siehe dies ). Also , wenn Sie eingegeben haben __dirnamein /d1/d2/myscript.js, wäre der Wert /d1/d2.

Im Gegensatz dazu erhalten .Sie das Verzeichnis, aus dem Sie den nodeBefehl in Ihrem Terminalfenster (dh Ihrem Arbeitsverzeichnis) ausgeführt haben, wenn Sie Bibliotheken wie pathund verwenden fs. Technisch gesehen beginnt es als Ihr Arbeitsverzeichnis, kann aber mit geändert werden process.chdir().

Die Ausnahme ist, wenn Sie .mit verwenden require(). Der Pfad darin requireist immer relativ zu der Datei, die den Aufruf von enthält require.

Zum Beispiel...

Angenommen, Ihre Verzeichnisstruktur ist

/dir1
  /dir2
    pathtest.js

und pathtest.jsenthält

var path = require("path");
console.log(". = %s", path.resolve("."));
console.log("__dirname = %s", path.resolve(__dirname));

und du machst

cd /dir1/dir2
node pathtest.js

du erhältst

. = /dir1/dir2
__dirname = /dir1/dir2

Ihr Arbeitsverzeichnis ist /dir1/dir2so, wie .es aufgelöst wird. Da pathtest.jssich in befindet /dir1/dir2, __dirnamelöst sich das auch auf.

Wenn Sie das Skript jedoch von ausführen /dir1

cd /dir1
node dir2/pathtest.js

du erhältst

. = /dir1
__dirname = /dir1/dir2

In diesem Fall war Ihr Arbeitsverzeichnis /dir1so, dass es .aufgelöst wurde, aber __dirnameimmer noch aufgelöst wird /dir1/dir2.

Verwenden von .innen require...

Wenn dir2/pathtest.jsSie einen requireAufruf haben, eine Datei einzuschließen dir1, würden Sie dies immer tun

require('../thefile')

weil der Pfad darin requireimmer relativ zu der Datei ist, in der Sie ihn aufrufen. Es hat nichts mit Ihrem Arbeitsverzeichnis zu tun.


38
IMO, diese Erklärung ist etwas klarer als die aus der akzeptierten Antwort (Sie wissen, "das aktuelle Verzeichnis" ist dort etwas mehrdeutig).
Inkarnation

5
Genau. Ich werde die akzeptierte Antwort ändern. Bitte denken Sie daran, dass diese Antwort 2,5 Jahre nach der Annahme der ursprünglichen Antwort hinzugefügt wurde und ich sie erst jetzt (weitere 2 Jahre später) bemerkt habe. :) Besser spät als nie!
Thisissami

14
Es ist erwähnenswert, dass dies ./nicht immer das Verzeichnis ist, von dem aus der Knoten gestartet wurde. Es beginnt so, kann aber über geändert werden process.chdir(). Es ./handelt sich also immer um das aktuelle Arbeitsverzeichnis, von dem normalerweise der Verzeichnisknoten gestartet wurde, es sei denn, Ihr Code hat das Arbeitsverzeichnis explizit geändert.
Gilly3

3
Ich bin ein wenig verwirrt über die Verwendung. inside require part Wenn der Pfad inside require immer relativ zu der von Ihnen aufgerufenen Datei ist, sollte der Pfad dann nicht require ('../ thefile') statt require ('../ dir1 / thefile') sein? Ich dachte, die .. bringen die aktuelle Position des Pfades bereits eine Ebene von dir2 nach dir1 zurück. Müssen Sie noch dir1 in den Pfad einfügen oder vermisse ich etwas verstanden?
Andromada

1
Und wie würden Sie vorgehen, wenn Sie ../someDirein Skript verwenden müssen und den Befehl aus einem anderen Ordner ausführen möchten ?
Entwickler

154

./bezieht sich auf das aktuelle Arbeitsverzeichnis, außer in der require()Funktion. Bei Verwendung require()wird es ./in das Verzeichnis der aktuell aufgerufenen Datei übersetzt. __dirnameist immer das Verzeichnis der aktuellen Datei.

Zum Beispiel mit der folgenden Dateistruktur

/home/user/dir/files/config.json

{
  "hello": "world"
}

/home/user/dir/files/somefile.txt

text file

/home/user/dir/dir.js

var fs = require('fs');

console.log(require('./files/config.json'));
console.log(fs.readFileSync('./files/somefile.txt', 'utf8'));

Wenn ich cdin /home/user/dirund laufen node dir.jsIch werde kommen

{ hello: 'world' }
text file

Aber wenn ich das gleiche Skript ausführe, /home/user/bekomme ich

{ hello: 'world' }

Error: ENOENT, no such file or directory './files/somefile.txt'
    at Object.openSync (fs.js:228:18)
    at Object.readFileSync (fs.js:119:15)
    at Object.<anonymous> (/home/user/dir/dir.js:4:16)
    at Module._compile (module.js:432:26)
    at Object..js (module.js:450:10)
    at Module.load (module.js:351:31)
    at Function._load (module.js:310:12)
    at Array.0 (module.js:470:10)
    at EventEmitter._tickCallback (node.js:192:40)

Verwenden ./mit gearbeitet, requireaber nicht für fs.readFileSync. Das liegt daran, dass für fs.readFileSync, ./in den cwd übersetzt (in diesem Fall /home/user/). Und /home/user/files/somefile.txtexistiert nicht.


Oh, ich dachte, __dirname war das aktuelle Arbeitsverzeichnis ... danke für die Klarstellung!
Thisissami

Gibt es eine Möglichkeit, das Arbeitsverzeichnis der App mit fs zu referenzieren? Zum Beispiel versuche ich, eine Datei aus dem Arbeitsverzeichnis zu laden /movies, aber da sich mein Modul in einer Datei befindet /custom_modules/, __dirnameversucht ich , den Film /custom_modules/movies

2
Sie können ./oder verwenden process.cwd(). siehe nodejs.org/api/process.html#process_process_cwd
gefeiert

Es ist erwähnenswert, dass es keine gute Idee ist, __dirname über ./ in require-Anweisungen zu verwenden, da sie sich zwar im Knoten identisch verhalten, jedoch Probleme mit browserify-Builds für Pakete verursachen können, die ansonsten leicht vermieden werden können.
Jed Watson
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.