Wie erhalte ich mit Node.js den Pfad zum aktuellen Skript?


979

Wie würde ich den Pfad zum Skript in Node.js erhalten?

Ich weiß process.cwd, dass es das gibt , aber das bezieht sich nur auf das Verzeichnis, in dem das Skript aufgerufen wurde, nicht auf das Skript selbst. Angenommen, ich bin dabei /home/kyle/und führe den folgenden Befehl aus:

node /home/kyle/some/dir/file.js

Wenn ich anrufe process.cwd(), bekomme ich /home/kyle/nicht /home/kyle/some/dir/. Gibt es eine Möglichkeit, dieses Verzeichnis zu erhalten?


6
nodejs.org/docs/latest/api/globals.html der Dokumentationslink der akzeptierten Antwort.
Allenhwkim

Antworten:


1393

Ich fand es, nachdem ich die Dokumentation noch einmal durchgesehen hatte. Was ich suchte, waren die Variablen auf __filenameund __dirnameModulebene.

  • __filenameist der Dateiname des aktuellen Moduls. Dies ist der aufgelöste absolute Pfad der aktuellen Moduldatei. (ex: /home/kyle/some/dir/file.js)
  • __dirnameist der Verzeichnisname des aktuellen Moduls. (ex: /home/kyle/some/dir)

3
Wenn Sie nur den Verzeichnisnamen und nicht den vollständigen Pfad möchten, können Sie Folgendes tun: function getCurrentDirectoryName () {var fullPath = __dirname; var path = fullPath.split ('/'); var cwd = path [path.length-1]; return cwd; }
Anthony Martin

58
@AnthonyMartin __dirname.split ("/"). Pop ()
19h

6
Für diejenigen, die eine @ apx-Lösung ausprobieren (wie ich es getan habe :), funktioniert diese Lösung unter Windows nicht.
Laoujin

36
Oder einfach__dirname.split(path.sep).pop()
Burgi

47
Oderrequire('path').basename(__dirname);
Vyacheslav Cotruta

251

Im Grunde können Sie dies tun:

fs.readFile(path.resolve(__dirname, 'settings.json'), 'UTF-8', callback);

Verwenden Sie resolve (), anstatt mit '/' oder '\' zu verketten. Andernfalls treten plattformübergreifende Probleme auf.

Hinweis: __dirname ist der lokale Pfad des Moduls oder des enthaltenen Skripts. Wenn Sie ein Plugin schreiben, das den Pfad des Hauptskripts kennen muss, ist dies:

require.main.filename

oder, um nur den Ordnernamen zu erhalten:

require('path').dirname(require.main.filename)

16
Wenn Sie nur die JSON-Datei analysieren und mit ihr interagieren möchten, können Sie dies häufig einfacher über tun var settings = require('./settings.json'). Natürlich ist es synchron fs IO, also mach es nicht zur Laufzeit, aber zum Start ist es in Ordnung und sobald es geladen ist, wird es zwischengespeichert.
Isaacs

2
@ Marc Danke! Seit einiger Zeit habe ich mich um die Tatsache gekümmert, dass __dirname für jedes Modul lokal ist. Ich habe eine verschachtelte Struktur in meiner Bibliothek und muss an mehreren Stellen den Stamm meiner App kennen. Ich bin froh, dass ich jetzt weiß, wie das geht: D
Thijs Koerselman

Knoten V8: path.dirname (process.mainModule.filename)
wayofthefuture

Wenn Sie Windows nicht als echte Plattform betrachten, können wir die Lösung überspringen? BSD, Macos, Linux, Tizen, Symbian, Solaris, Android, Flattern, Webos alle verwenden / richtig?
Ray Foss


119

Dieser Befehl gibt das aktuelle Verzeichnis zurück:

var currentPath = process.cwd();

So verwenden Sie beispielsweise den Pfad zum Lesen der Datei:

var fs = require('fs');
fs.readFile(process.cwd() + "\\text.txt", function(err, data)
{
    if(err)
        console.log(err)
    else
        console.log(data.toString());
});

Für diejenigen, die Asynchron und Synchron nicht verstanden haben , siehe diesen Link ... stackoverflow.com/a/748235/5287072
DarckBlezzer

16
Genau das will das OP nicht ... die Anfrage ist nach dem Pfad des ausführbaren Skripts!
Caesarsol

3
Das aktuelle Verzeichnis ist eine ganz andere Sache. Wenn Sie so etwas wie ausführen cd /foo; node bar/test.js, wäre das aktuelle Verzeichnis /foo, aber das Skript befindet sich in /foo/bar/test.js.
rjmunro

Es ist keine gute Antwort. Es ist ein logisches Problem, dass dies ein viel kürzerer Weg sein kann, als Sie erwarten.
kris_IV

Warum würdest du das jemals tun? Wenn die Datei relativ zum aktuellen Verzeichnis text.txtwäre, das Sie gerade lesen könnten, und es funktionieren würde, müssen Sie nicht den absoluten Pfad
erstellen

103

Verwenden Sie __dirname !!

__dirname

Der Verzeichnisname des aktuellen Moduls. Dies ist das gleiche wie der path.dirname () des __filename.

Beispiel: Ausführen des Knotens example.js aus / Users / mjr

console.log(__dirname);
// Prints: /Users/mjr
console.log(path.dirname(__filename));
// Prints: /Users/mjr

https://nodejs.org/api/modules.html#modules_dirname

Für ESModules möchten Sie Folgendes verwenden: import.meta.url


1
Dies überlebt auch Symlinks. Wenn Sie also einen Bin erstellen und eine Datei suchen müssen, z. B. path.join (__ dirname, "../example.json"); Es wird immer noch funktionieren, wenn Ihre Binärdatei in node_modules / .bin
Jason

2
Diese Antwort wurde nicht nur Jahre zuvor gegeben, sie funktioniert auch nicht mehr mit ES-Modulen .
Dan Dascalescu

48

Wenn es um das Hauptskript geht, ist es so einfach wie:

process.argv[1]

Aus der Node.js-Dokumentation :

process.argv

Ein Array mit den Befehlszeilenargumenten. Das erste Element ist 'node', das zweite Element ist der Pfad zur JavaScript-Datei . Die nächsten Elemente sind zusätzliche Befehlszeilenargumente.

Wenn Sie den Pfad einer Moduldatei kennen müssen, verwenden Sie __Dateiname .


3
Könnte der Downvoter bitte erklären, warum dies nicht empfohlen wird?
Tamlyn

1
@Tamlyn Vielleicht, weil dies process.argv[1]nur für das Hauptskript gilt, während __filenameauf die ausgeführte Moduldatei verwiesen wird. Ich aktualisiere meine Antwort, um den Unterschied hervorzuheben. Trotzdem sehe ich nichts falsches daran process.argv[1]. Kommt auf die Bedürfnisse an.
Lukasz Wiktor

10
Wenn das Hauptskript mit einem Knotenprozessmanager wie pm2 process.argv [1] gestartet wurde, verweist es auf die ausführbare Datei des Prozessmanagers /usr/local/lib/node_modules/pm2/lib/ProcessContainerFork.js
user3002996

34

Node.js 10 unterstützt ECMAScript - Module , wo __dirnameund __filenamesind nicht mehr verfügbar .

Um dann den Pfad zum aktuellen ES-Modul zu erhalten, muss Folgendes verwendet werden:

import { fileURLToPath } from 'url';

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

Und für das Verzeichnis mit dem aktuellen Modul:

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

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

Wie würde ich wissen, ob ich ein ES-Modul schreibe oder nicht? Ist es nur eine Frage der Knotenversion, die ich verwende, oder ob ich Import / Export-Schlüsselwörter verwende?
Ed Brannin

2
ES-Module nur mit --experimental-modulesFlag verfügbar .
Nickensoul

1
--experimental-modules ist nur erforderlich, wenn Sie die Knotenversion <13.2 ausführen. Nennen Sie einfach die Datei .mjs anstatt .js
Brent


24

Jedes Node.js-Programm hat einige globale Variablen in seiner Umgebung, die einige Informationen über Ihren Prozess darstellen und eine davon sind __dirname.


Diese Antwort wurde nicht nur Jahre zuvor gegeben, __dirname sondern funktioniert auch nicht mehr mit ES-Modulen .
Dan Dascalescu

Es geht um NodeJs 10, aber diese Antwort wurde 2016 veröffentlicht.
Hazarapet Tunanyan

Ich kenne. Antworten können aktualisiert werden, wenn sich die Technologie ändert.
Dan Dascalescu

13

Ich weiß, dass dies ziemlich alt ist, und die ursprüngliche Frage, auf die ich geantwortet habe, ist als doppelt markiert und hier gerichtet, aber ich bin auf ein Problem gestoßen, bei dem versucht wurde, Jasminreporter zum Arbeiten zu bringen, und die Idee, dass ich ein Downgrade durchführen musste, hat mir nicht gefallen damit es funktioniert. Ich fand heraus, dass Jasmin-Reporter den savePath nicht korrekt auflösten und die Ausgabe des Berichtsordners tatsächlich in das Verzeichnis Jasmin-Reporter anstatt in das Stammverzeichnis, in dem ich gulp ausgeführt habe, ablegten. Damit dies korrekt funktioniert, habe ich process.env.INIT_CWD verwendet , um das erste aktuelle Arbeitsverzeichnis abzurufen , das das Verzeichnis sein sollte, in dem Sie gulp ausgeführt haben. Hoffe das hilft jemandem.

var reporters = require('jasmine-reporters');
var junitReporter = new reporters.JUnitXmlReporter({
  savePath: process.env.INIT_CWD + '/report/e2e/',
  consolidateAll: true,
  captureStdout: true
 });

8

Sie können process.env.PWD verwenden, um den aktuellen Pfad des App-Ordners abzurufen.


2
OP fragt nach dem angeforderten "Pfad zum Skript". PWD, was für so etwas wie Process Working Directory steht, ist das nicht. Auch die Formulierung der "aktuellen App" ist irreführend.
dmcontador

7

Wenn Sie pkgIhre App zum Packen verwenden, finden Sie diesen Ausdruck nützlich:

appDirectory = require('path').dirname(process.pkg ? process.execPath : (require.main ? require.main.filename : process.argv[0]));
  • process.pkgGibt an, ob die App von gepackt wurde pkg.

  • process.execPathEnthält den vollständigen Pfad der ausführbaren Datei, die /usr/bin/nodefür den direkten Aufruf von scripts ( node test.js) oder der gepackten App gleich oder ähnlich ist .

  • require.main.filename Enthält den vollständigen Pfad des Hauptskripts, ist jedoch leer, wenn Node im interaktiven Modus ausgeführt wird.

  • __dirnameEnthält den vollständigen Pfad des aktuellen Skripts, daher verwende ich es nicht (obwohl es möglicherweise das ist, was OP verlangt; dann sollten Sie besser appDirectory = process.pkg ? require('path').dirname(process.execPath) : (__dirname || require('path').dirname(process.argv[0]));beachten, dass der interaktive Modus __dirnameleer ist.

  • Verwenden Sie im interaktiven Modus entweder process.argv[0]den Pfad zur ausführbaren Node-Datei oder process.cwd()das aktuelle Verzeichnis.


3

Verwenden Sie die basenameMethode des pathModuls:

var path = require('path');
var filename = path.basename(__filename);
console.log(filename);

Hier ist die Dokumentation, aus der das obige Beispiel stammt.

Wie Dan betonte, arbeitet Node an ECMAScript-Modulen mit dem Flag "--experimental-modules". Knoten 12 unterstützt__dirname__filename weiterhin und wie oben.


Wenn Sie das --experimental-modulesFlag verwenden, gibt es einen alternativen Ansatz .

Die Alternative besteht darin, den Pfad zum aktuellen ES-Modul abzurufen :

const __filename = new URL(import.meta.url).pathname;

Und für das Verzeichnis mit dem aktuellen Modul:

import path from 'path';

const __dirname = path.dirname(new URL(import.meta.url).pathname);

-2

Wenn Sie mehr wie $ 0 in einem Shell-Skript möchten, versuchen Sie Folgendes:

var path = require('path');

var command = getCurrentScriptPath();

console.log(`Usage: ${command} <foo> <bar>`);

function getCurrentScriptPath () {
    // Relative path from current working directory to the location of this script
    var pathToScript = path.relative(process.cwd(), __filename);

    // Check if current working dir is the same as the script
    if (process.cwd() === __dirname) {
        // E.g. "./foobar.js"
        return '.' + path.sep + pathToScript;
    } else {
        // E.g. "foo/bar/baz.js"
        return pathToScript;
    }
}

__dirnameund __filenamesind mit ES-Modulen nicht mehr verfügbar .
Dan Dascalescu
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.