Knoten __Dirnname nicht definiert


137

Aus dem Knotenhandbuch sehe ich, dass ich das Verzeichnis einer Datei mit __dirnameabrufen kann, aber aus der REPL scheint dies undefiniert zu sein. Ist das ein Missverständnis auf meiner Seite oder wo liegt der Fehler?

$ node
> console.log(__dirname)
ReferenceError: __dirname is not defined
    at repl:1:14
    at REPLServer.eval (repl.js:80:21)
    at Interface.<anonymous> (repl.js:182:12)
    at Interface.emit (events.js:67:17)
    at Interface._onLine (readline.js:162:10)
    at Interface._line (readline.js:426:8)
    at Interface._ttyWrite (readline.js:603:14)
    at ReadStream.<anonymous> (readline.js:82:12)
    at ReadStream.emit (events.js:88:20)
    at ReadStream._emitKey (tty.js:320:10)


Ich habe dieses Problem bei der Verwendung von eslint erhalten, das ich fälschlicherweise "browser": trueanstelle von "node": true.eslintrc.json festgelegt habe.
Toivo Säwén

Antworten:


186

__dirnamewird nur in Skripten definiert. Es ist nicht in REPL verfügbar.

Versuchen Sie, ein Skript zu erstellen a.js

console.log(__dirname);

und führen Sie es aus:

node a.js

Sie werden __dirnamegedruckt sehen.

Hintergrunderklärung hinzugefügt: __dirnamebedeutet "Das Verzeichnis dieses Skripts". In REPL haben Sie kein Skript. Daher __dirnamehätte keine wirkliche Bedeutung.


5
Außerdem können Sie einige der globalen Variablen in RequireJS-Modulen nicht verwenden. Wenn Sie RequireJS auf der Serverseite verwenden, lesen Sie stackoverflow.com/questions/9027429/… .
Auge

1
Ja, das sollte wirklich zur Antwort Eye hinzugefügt werden, denn das hat mich dazu gebracht.
Tomáš Zato - Wiedereinsetzung Monica

3
Das nicht in das Ladeskript der REPL aufzunehmen, ist widerlich. Ich kann mir keinen Grund
vorstellen,

Ich habe eine Skriptdatei geladen, während ich mich in der REPL befand .load script.js. Es ist schade, dass __dirname immer noch nicht in script.js verfügbar ist
Kevin Wheeler

upvoted! sparte mir 15 Minuten, als ich mich fragte, wtf passiert
PirateApp

96

Aufbauend auf den hier vorhandenen Antworten können Sie dies in Ihrer REPL definieren:

__dirname = path.resolve(path.dirname(''));

Oder:

__dirname = path.resolve();

Wenn keine pathSegmente übergeben werden, path.resolve()wird der absolute Pfad des aktuellen Arbeitsverzeichnisses zurückgegeben.


Oder @ Jthorpes Alternativen:

__dirname = process.cwd();
__dirname = fs.realpathSync('.');
__dirname = process.env.PWD

Wenn Sie verwenden nesh, können Sie dies als Teil Ihres Ladeskripts definieren. Es ist
schick

1
oder __dirname = process.cwd()oder __dirname=fs.realpathSync('.')oder__dirname = process.env.PWD
Jthorpe

1
path.dirnamescheint in der neuesten Hauptversion keine Nicht-String-Werte mehr zu akzeptieren 6.0.0, daher funktioniert der erste Vorschlag in dieser Antwort nicht.
Tryse

30

In ES6 verwenden Sie:

import path from 'path';
const __dirname = path.resolve();

auch verfügbar, wenn der Knoten mit aufgerufen wird --experimental-modules


Sie müssen keine Kernmodule in die REPL importieren. es wird sie im laufenden Betrieb für Sie laden.
c24w

Dies gibt das aktuelle Arbeitsverzeichnis an, nicht das Verzeichnis der aktuellen .jsDatei.
Dirbaio

@Dirbaio, was wäre die aktuelle .jsDatei, wenn Sie in der REPL sind?
c24w

@ c24w gerade überprüft, es scheint das CWD
Dirbaio

@Dirbaio Ich denke, das war mein Punkt. Wenn Sie die REPL eingeben, gibt es keine aktuelle JS-Datei. Was würdest du sein wollen __dirname, wenn nicht das CWD?
c24w

8

Wie @qiao sagte, können Sie nicht __dirnamein der Knotenreplikation verwenden. Wenn Sie diesen Wert jedoch in der Konsole benötigen, können Sie path.resolve()oder verwenden path.dirname(). Obwohl, path.dirname()geben Sie nur ein "." also wahrscheinlich nicht so hilfreich. Seien Sie sicher require('path').


3

Scheint, als könnten Sie dies auch tun:

__dirname=fs.realpathSync('.');

Natürlich nicht vergessen fs=require('fs')

(In Knotenskripten ist es nicht wirklich global, sondern nur auf Modulebene definiert.)


Sie müssen keine Kernmodule in der REPL benötigen. es wird sie im laufenden Betrieb für Sie laden.
c24w

2

Ich habe ein Skript aus einer Batchdatei als SYSTEM-Benutzer und alle Variablen wie ausgeführt process.cwd(), path.resolve()und alle anderen Methoden haben mir den Pfad zum Ordner C: \ Windows \ System32 anstelle des tatsächlichen Pfads gegeben. Während der Experimente habe ich festgestellt, dass der Stapel beim Auslösen eines Fehlers einen echten Pfad zur Knotendatei enthält.

Hier ist ein sehr hackiger Weg, um einen echten Pfad zu erhalten, indem ein Fehler ausgelöst und der Pfad aus e.stack extrahiert wird. Verwende nicht.

// this should be the name of currently executed file
const currentFilename = 'index.js';

function veryHackyGetFolder() {
  try {
    throw new Error();
  } catch(e) {
    const fullMsg = e.stack.toString();
    const beginning = fullMsg.indexOf('file:///') + 8;
    const end = fullMsg.indexOf('\/' + currentFilename);
    const dir = fullMsg.substr(beginning, end - beginning).replace(/\//g, '\\');
    return dir;
  }
}

Verwendung

const dir = veryHackyGetFolder();

Wenn Sie dies nicht durch die REPL läuft, Sie können verwenden __dirnameund __filename.
c24w

Dies ist die einzige Antwort, die zumindest versucht, eine korrekte Lösung bereitzustellen.
Tomáš Zato - Wiedereinsetzung von Monica

@ c24w Ich habe __dirname, __filename und alles andere ausprobiert. In meinem Fall hat keine Standardlösung funktioniert. Hier ist mein Projekt, das einen Prozess als SYSTEM vom Taskplaner aus ausführt, wenn Sie sich langweilen. Github.com/DVLP/Unscheduler. Jede Standardlösung, die sonst funktioniert, ist offensichtlich besser als mein Hack oben :)
Pawel

2

Ich habe auch versucht, meinen Pfad mit zu verbinden, path.join(__dirname, 'access.log')aber es hat den gleichen Fehler ausgelöst.

So habe ich es behoben:

Ich habe zuerst das Pfadpaket importiert und eine Variable mit dem Namen deklariert __dirnameund dann die resolve Pfadmethode aufgerufen .

In CommonJS

var path = require("path");

var __dirname = path.resolve();

In ES6 +

import path  from 'path';

const __dirname = path.resolve();

Viel Spaß beim Codieren .......


1

Obwohl es nicht die Lösung für dieses Problem ist, möchte ich es hinzufügen, da es anderen helfen kann.

Sie sollten zwei Unterstriche vor dirname haben, nicht einen Unterstrich ( __dirnamenicht _dirname).

NodeJS Docs


__dirname (mit zwei Unterstrichen) funktioniert nicht in der REPL
Aaron J Spetner

1

Wenn Sie node __dirname not definedmit gekommen sind node --experimental-modules, können Sie tun:

const __dirname = path.dirname(import.meta.url)
                      .replace(/^file:\/\/\//, '') // can be usefull

Arbeiten Sie im anderen Fall nur mit dem aktuellen Verzeichnis / pwd, nicht mit einem anderen Verzeichnis.


1

Wenn Sie mit Node.js Module , __dirnameund __filenamegibt es nicht.

Aus der Node.js-Dokumentation :

Keine Notwendigkeit, Exporte, module.exports, __Dateiname, __Dirname

Diese CommonJS-Variablen sind in ES-Modulen nicht verfügbar.

require kann mit in ein ES-Modul importiert werden module.createRequire() .

Äquivalente von __filenameund __dirnamekönnen in jeder Datei erstellt werden über import.meta.url:

import { fileURLToPath } from 'url';
import { dirname } from 'path';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

https://nodejs.org/api/esm.html#esm_no_require_exports_module_exports_filename_dirname


0

manchmal erstellen wir eine Datei mit der Erweiterung .js und fügen consol.log (_dirname) hinzu; Aber wir haben Fehler, wir haben es eilig, also vergessen wir, vor dem "Verzeichnisnamen" einen weiteren Unterstrich einzufügen, damit wir auf Referenzfehler stoßen. Die korrekte Syntax lautet consol.log (__ Verzeichnisname).

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.