Bestimmen Sie das Arbeitsverzeichnis der Befehlszeile, wenn Sie das Node Bin-Skript ausführen

120

Ich erstelle eine Knotenbefehlszeilenschnittstelle. Es wird global installiert und verwendet eine Bin-Datei zur Ausführung.

Ich habe vor, ein Befehlsfenster im Stammverzeichnis der Dateien zu öffnen, an denen ich arbeite, und dann einfach den Befehl auszuführen. Ich konnte jedoch das aktuelle Arbeitsverzeichnis nicht ermitteln, da process.cwd()das Verzeichnis des Knotenpakets zurückgegeben wird. Ich habe anfangs angenommen, dass es unmöglich ist, da der Code mit einer Batch-Datei als Wrapper ausgeführt wird (so können Bin-Dateien am Anfang ohne Knoten ausgeführt werden), aber das Kaffeeskript schafft es. Ich habe mir die Quelle des Kaffeeskripts angesehen, konnte ihr aber nicht folgen (nicht erfahren genug).

Um es selbst zu testen, erstellen Sie ein Paket mit dieser Datei package.json:

{
  "name": "test-package",
  "version": "1.0.0",
  "bin": {
    "test-package":  "./bin/test-package"
  },
  "main": "/lib/test"
}

Diese Testpaketdatei in bin:

#!/usr/bin/env node

var path = require('path');
var fs   = require('fs');
var lib  = path.join(path.dirname(fs.realpathSync(__filename)), '../lib');

require(lib + '/test');

Könnte jemand etwas Licht ins Dunkel bringen?

Versuchen Sie dann, das Befehlszeilenverzeichnis in lib / test abzurufen.

Daniel Chatfield
quelle

Antworten:

196
  • process.cwd() Gibt das Verzeichnis zurück, in dem der Befehl ausgeführt wurde (nicht das Verzeichnis des Knotenpakets), wenn er nicht von 'process.chdir' innerhalb der Anwendung geändert wurde.
  • __filename Gibt den absoluten Pfad zur Datei zurück, in der sie abgelegt ist.
  • __dirnameGibt den absoluten Pfad zum Verzeichnis von zurück __filename.

Wenn Sie Dateien aus Ihrem Modulverzeichnis laden müssen, müssen Sie relative Pfade verwenden.

require('../lib/test');

anstatt

var lib  = path.join(path.dirname(fs.realpathSync(__filename)), '../lib');

require(lib + '/test');

Es ist immer relativ zu der Datei, von der es aufgerufen wurde, und hängt nicht vom aktuellen Arbeitsverzeichnis ab.

Vadim Baryshev
quelle
2
Gibt process.chdir()es danach eine Möglichkeit, das Original zu erhalten?
reergymerej
@reergymerej Sie möchten wahrscheinlich zuerst cwd speichern, bevor Sie chdir () ausführen (z. B. var originalCwd = process.cwd();dann Ihr ausführen process.chdir(), und Sie können anschließend zum Original zurückkehren).
Wirbel
ist ../lib/test tragbar?
Sebastian
Nein, es ist keine tragbare Lösung, da Windows Backslashes verwendet. Wenn Sie also versuchen, es in Windows auszuführen, funktioniert es nicht.
Zachdyer
1
Für NodeJS ist das eigentlich alles das Gleiche. Selbst unter Windows können Sie bequem relative Pfade auf Unix-Weise benötigen. So../lib/test also portabel, während das Windows-Gegenstück ..\lib\testnicht ...
Christian Ulbrich
47

Aktuelles Arbeitsverzeichnis

Um das aktuelle Arbeitsverzeichnis abzurufen, können Sie Folgendes verwenden:

process.cwd()

Beachten Sie jedoch, dass einige Skripte, insbesondere gulp, das aktuelle Arbeitsverzeichnis mit ändern process.chdir().

Knotenmodulpfad

Sie können den Pfad des aktuellen Moduls abrufen mit:

  • __filename
  • __dirname

Originalverzeichnis (wo der Befehl initiiert wurde)

Wenn Sie ein Skript über die Befehlszeile ausführen und das ursprüngliche Verzeichnis möchten, in dem das Skript ausgeführt wurde, unabhängig davon, in welchem ​​Verzeichnis das Skript gerade ausgeführt wird, können Sie Folgendes verwenden:

process.env.INIT_CWD

Originalverzeichnis bei der Arbeit mit NPM-Skripten

Manchmal ist es wünschenswert, ein NPM-Skript im aktuellen Verzeichnis und nicht im Stammverzeichnis des Projekts auszuführen.

Diese Variable ist in npm-Paketskripten verfügbar als:

$INIT_CWD.

Sie müssen eine aktuelle Version von NPM ausführen. Wenn diese Variable nicht verfügbar ist, stellen Sie sicher, dass NPM auf dem neuesten Stand ist.

Auf diese Weise können Sie auf den aktuellen Pfad in Ihrer package.json zugreifen, z.

scripts: {
  "customScript": "gulp customScript --path $INIT_CWD"
}
überleuchtet
quelle
process.env.INIT_CWDgibt das package.json
Verzeichnis
2
Achtung, $ INIT_CWD funktioniert nur unter Linux. Für Windows müssen Sie% INIT_CWD% verwenden. Ich denke, dieses Problem kann mit npmjs.com/package/cross-env behoben werden , aber ich habe es nicht selbst versucht
Stephanie
3

Wenn Sie alternativ nur das aktuelle Verzeichnis des aktuellen NodeJS-Skripts abrufen möchten, können Sie auch etwas Einfaches ausprobieren. Beachten Sie, dass dies in der Node CLI selbst nicht funktioniert:

var fs = require('fs'),
    path = require('path');

var dirString = path.dirname(fs.realpathSync(__filename));

// output example: "/Users/jb/workspace/abtest"
console.log('directory to start walking...', dirString);
John Paul Barbagallo
quelle
3

path.resolve('.')ist auch eine zuverlässige und saubere Option, weil wir fast immer require('path'). Sie erhalten den absoluten Pfad des Verzeichnisses, von dem aus es aufgerufen wird.

sziraqui
quelle
0

Folgendes hat bei mir funktioniert:

console.log(process.mainModule.filename);
Etienne Martin
quelle