Określ katalog roboczy wiersza poleceń podczas uruchamiania skryptu bin węzła

121

Tworzę interfejs wiersza poleceń węzła. Jest instalowany globalnie i do wykonania używa pliku bin.

Planuję otworzyć okno poleceń w katalogu głównym plików, nad którymi pracuję, a następnie po prostu uruchomić polecenie, jednak nie mogłem określić bieżącego katalogu roboczego, ponieważ zwracam process.cwd()katalog pakietu węzła. Początkowo zakładałem, że skoro kod jest wykonywany przy użyciu pliku wsadowego jako opakowania (w ten sposób pliki bin mogą działać bez węzła na początku), to jest to niemożliwe, ale coffee-script udaje się to zrobić. Rzuciłem okiem na źródło skryptu kawy, ale nie mogłem go śledzić (nie miałem wystarczającego doświadczenia).

Aby przetestować to samodzielnie, utwórz pakiet z tym plikiem package.json:

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

ten plik pakietu testowego w 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');

Czy ktoś mógłby rzucić na to trochę światła.

a następnie spróbuj pobrać katalog wiersza poleceń wewnątrz lib / test.

Daniel Chatfield
źródło

Odpowiedzi:

196
  • process.cwd() zwraca katalog, w którym polecenie zostało wykonane (nie katalog pakietu węzłów), jeśli nie zostało zmienione przez „process.chdir” wewnątrz aplikacji.
  • __filename zwraca bezwzględną ścieżkę do pliku, w którym jest umieszczony.
  • __dirnamezwraca bezwzględną ścieżkę do katalogu __filename.

Jeśli chcesz załadować pliki z katalogu modułu, musisz użyć ścieżek względnych.

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

zamiast

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

require(lib + '/test');

Jest zawsze względna w stosunku do pliku, z którego została wywołana i nie zależy od bieżącego katalogu roboczego.

Vadim Baryshev
źródło
2
Czy process.chdir()jest jakiś sposób na zdobycie oryginału?
reergymerej
@reergymerej Prawdopodobnie będziesz chciał najpierw zapisać cwd przed wykonaniem chdir () (np. var originalCwd = process.cwd();następnie wykonaj swoje process.chdir()i możesz później wrócić do oryginału).
Obrót
jest ../lib/testprzenośny?
Sebastian
Nie. Nie jest to rozwiązanie przenośne, ponieważ w systemie Windows stosowane są ukośniki odwrotne. Więc jeśli spróbujesz uruchomić go w systemie Windows, to nie zadziała.
zachdyer
1
Właściwie dla NodeJS to wszystko jest takie samo. Nawet w systemie Windows można wygodnie wymagać ścieżek względnych w sposób uniksowy. Więc ../lib/testjest przenośny, podczas gdy odpowiednik Windowsa ..\lib\testnie jest ...
Christian Ulbrich
48

Aktualny katalog roboczy

Aby uzyskać bieżący katalog roboczy, możesz użyć:

process.cwd()

Należy jednak pamiętać, że niektóre skrypty, w szczególności gulp, zmienią bieżący katalog roboczy z process.chdir().

Ścieżka modułu węzła

Możesz uzyskać ścieżkę do bieżącego modułu za pomocą:

  • __filename
  • __dirname

Katalog oryginalny (gdzie zainicjowano polecenie)

Jeśli uruchamiasz skrypt z wiersza poleceń i chcesz mieć oryginalny katalog, z którego skrypt został uruchomiony, niezależnie od katalogu, w którym skrypt aktualnie działa, możesz użyć:

process.env.INIT_CWD

Oryginalny katalog podczas pracy ze skryptami NPM

Czasami pożądane jest uruchomienie skryptu NPM w bieżącym katalogu, a nie w katalogu głównym projektu.

Ta zmienna jest dostępna w skryptach pakietu npm jako:

$INIT_CWD.

Musisz używać najnowszej wersji NPM. Jeśli ta zmienna nie jest dostępna, upewnij się, że NPM jest aktualny.

Umożliwi to dostęp do bieżącej ścieżki w pliku package.json, na przykład:

scripts: {
  "customScript": "gulp customScript --path $INIT_CWD"
}
superluminium
źródło
process.env.INIT_CWDzwraca reż zpackage.json
vaughan
2
Uważaj, $ INIT_CWD działa tylko na Linuksie. W przypadku systemu Windows musisz użyć% INIT_CWD%. Myślę, że ten problem można rozwiązać za pomocą npmjs.com/package/cross-env , ale sam tego nie próbowałem
Stephanie
3

Alternatywnie, jeśli chcesz uzyskać wyłącznie bieżący katalog bieżącego skryptu NodeJS, możesz spróbować czegoś prostego. Zauważ, że to nie zadziała w samym interfejsie wiersza polecenia węzła:

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
źródło
3

path.resolve('.')jest również niezawodną i czystą opcją, ponieważ prawie zawsze require('path'). Poda ci bezwzględną ścieżkę do katalogu, z którego jest wywołany.

sziraqui
źródło
0

Oto, co zadziałało dla mnie:

console.log(process.mainModule.filename);
Etienne Martin
źródło