Zmień katalog roboczy w moim bieżącym kontekście powłoki podczas uruchamiania skryptu Node

114

Próbuję zmienić katalog roboczy mojego skryptu Node.js, gdy jest on uruchamiany ze skryptu bin. Mam coś takiego:

#!/usr/bin/env node
process.chdir('/Users')

Kiedy następnie uruchamiam ten plik za pomocą ./bin/nodefile, kończy się, ale katalog roboczy bieżącego kontekstu powłoki nie uległ zmianie. Próbowałem też shelljów , ale to też nie działa.

Jaki jest najlepszy sposób, aby to zrobić? Rozumiem, że to działa, ale to tylko oddzielny proces.

Jonovono
źródło
jakie macie dowody, że cwd się nie zmieniło? Pamiętaj, że ścieżki używane w require () i cwd to dwie różne rzeczy.
jeesty
Czy istnieje sposób, aby to zrobić w systemie Windows?
Phillip,

Odpowiedzi:

146

Właściwy sposób zmiany katalogów to w rzeczywistości process.chdir(directory). Oto przykład z dokumentacji :

console.log('Starting directory: ' + process.cwd());
try {
  process.chdir('/tmp');
  console.log('New directory: ' + process.cwd());
}
catch (err) {
  console.log('chdir: ' + err);
}

Można to również przetestować w REPL Node.js:

[monitor@s2 ~]$ node
> process.cwd()
'/home/monitor'
> process.chdir('../');
undefined
> process.cwd();
'/home'
heksacyjanek
źródło
Ups. Tak, to jest polecenie, którego faktycznie używam. Jednak gdy używam go w prostym skrypcie, nadal wydaje się, że nie działa (po zamknięciu skryptu nadal jestem w starym katalogu) Jeśli wywołuję process.cwd (), to mówi, że jestem w katalogu, w którym powinienem być, ale mój terminal, jeśli zadzwonię do pwd, mówi, że jestem w czymś innym. Ponieważ to inny proces?
Jonovono
10
Metoda zmienia bieżący katalog roboczy procesu , a nie powłokę. O ile wiem, zmiana zewnętrznego cwd działającego procesu jest dość złożona i nie jest zalecana. Jaki jest twój powód, dla którego chcesz to zrobić?
heksacyjanek
3
Hmm. Ok dzięki. Powodem, dla którego chcę to zrobić, jest to, że tworzę aplikację terminalową do organizowania moich projektów. Zasadniczo chcę mieć możliwość wyświetlenia moich projektów i łatwej zmiany bieżącej lokalizacji powłoki na to. Teraz, kiedy o tym pomyślę, przyjrzę się, jak z ( github.com/rupa/z ) to robi. Chociaż odbywa się to w bash. Może mógłbym to zrobić w jabłkowym skrypcie?
Jonovono
@hexacyanide dzięki za dodanie było kłopotliwe, ponieważ zmiany nie zostały wyrównane
Eugen Sunic
33

Nie ma wbudowanej metody dla Node, aby zmienić CWD podstawowej powłoki, na której działa proces Node.

Państwo może zmienić bieżący katalog roboczy w procesie węzła za pomocą polecenia process.chdir().

var process = require('process');
process.chdir('../');

Gdy proces Node istnieje, znajdziesz się z powrotem w CWD, w którym rozpocząłeś proces.

dthree
źródło
14

To, co próbujesz zrobić, nie jest możliwe. Powodem tego jest fakt, że w systemie POSIX (Linux, OSX itp.) Proces potomny nie może modyfikować środowiska procesu nadrzędnego. Obejmuje to modyfikację katalogu roboczego procesu nadrzędnego i zmiennych środowiskowych.

Kiedy jesteś w linii poleceń i idziesz wykonać skrypt Node, twój bieżący proces ( bash, zshcokolwiek) odrodzi nowy proces, który ma swoje własne środowisko, zazwyczaj kopię twojego obecnego środowiska (można to zmienić poprzez wywołania systemowe ; ale to wykracza poza zakres tej odpowiedzi), pozwalając temu procesowi robić wszystko, co musi, w całkowitej izolacji. Po zakończeniu podprocesu kontrola jest przekazywana z powrotem do procesu powłoki, gdzie nie ma to wpływu na środowisko.

Istnieje wiele powodów takiego stanu rzeczy, ale po pierwsze, wyobraź sobie, że wykonałeś skrypt w tle (przez ./foo.js &) i podczas jego działania zaczął on zmieniać katalog roboczy lub nadpisywać PATH. To byłby koszmar.

Jeśli musisz wykonać jakieś czynności, które wymagają zmiany katalogu roboczego twojej powłoki, będziesz musiał napisać funkcję w swojej powłoce. Na przykład, jeśli używasz Bash, możesz umieścić to w swoim ~/.bash_profile:

do_cool_thing() {
  cd "/Users"
  echo "Hey, I'm in $PWD"
}

a wtedy ta fajna rzecz jest wykonalna:

$ pwd
/Users/spike
$ do_cool_thing
Hey, I'm in /Users
$ pwd
/Users

Jeśli potrzebujesz dodatkowo zrobić bardziej złożone rzeczy, zawsze możesz wywołać swój skrypt nodejs z tej funkcji.

To jedyny sposób, w jaki możesz osiągnąć to, co próbujesz zrobić.

Spike Grobstein
źródło
10

Krótka odpowiedź: nie (łatwa?) Droga, ale możesz zrobić coś, co służy twojemu celowi.

Zrobiłem podobne narzędzie (małe polecenie, które na podstawie opisu projektu ustawia środowisko, ścieżki, katalogi itp.). To, co robię, to konfiguruję wszystko, a następnie spawnuję powłokę z:

spawn('bash', ['-i'], {
  cwd: new_cwd,
  env: new_env,
  stdio: 'inherit'
});

Po wykonaniu będziesz w powłoce z nowym katalogiem (i, w moim przypadku, środowiskiem). Oczywiście możesz zmienić bash na dowolną preferowaną powłokę. Główne różnice w stosunku do tego, o co prosiłeś, to:

  • Jest dodatkowy proces, więc ...
  • trzeba napisać „wyjście”, żeby wrócić, a potem ...
  • po zaistnieniu wszystkie zmiany są cofane.

Jednak dla mnie te różnice są pożądane.

Ewolucja
źródło