Змініть робочий каталог у моєму поточному контексті оболонки під час запуску сценарію Node


114

Я намагаюся змінити робочий каталог мого скрипта Node.js, коли він запускається зі скрипту bin. У мене є щось таке:

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

Коли я запускаю цей файл із ./bin/nodefile, він виходить, але робочий каталог поточного контексту оболонки не змінився. Я також спробував shelljs , але це теж не працює.

Який найкращий спосіб зробити це? Я розумію, що це працює, але це просто в окремому процесі.


які докази у вас є, що cwd не змінився? Пам’ятайте, що шляхи, які використовуються у вимагають () та cwd - це дві різні речі.
jeesty

Чи є спосіб це зробити в Windows?
Філліп

Відповіді:


146

Правильний спосіб зміни каталогів насправді за допомогою process.chdir(directory). Ось приклад з документації :

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

Це також перевіряється в REPL Node.js:

[monitor@s2 ~]$ node
> process.cwd()
'/home/monitor'
> process.chdir('../');
undefined
> process.cwd();
'/home'

На жаль Так, це команда, яку я насправді використовую. Однак, коли я використовую його у простому сценарії, він все ще не працює (як тільки сценарій закінчується, я все ще перебуваю в старому каталозі) Якщо я викликаю process.cwd (), він говорить, що я в каталозі, я повинен бути, але мій термінал, якщо я дзвоню pwd, говорить, що я в чомусь інакше. Тому що це інший процес?
Іваново

10
Метод змінює поточний робочий каталог процесу , а не оболонку. Наскільки я знаю, зміна зовнішнього cdd запущеного процесу досить складна і не рекомендується. Яка ваша причина цього хотіти?
гексаціанід

3
Хм. Добре, дякую. Ну, тому я хочу це зробити, тому що я роблю термінальний додаток для організації своїх проектів. Тому я хочу мати можливість перелічити свої проекти та легко змінити поточне розташування оболонки на таке. Тепер, коли я замислююся над цим, я збираюся розібратися, як z ( github.com/rupa/z ) робить це. Хоча це робиться в баш. Я міг би це зробити в яблучному сценарії?
Іваново

@hexacyanide спасибі за додавання турбував, оскільки зміни не узгоджувались
Eugen Sunic

33

Не існує вбудованого методу для Node для зміни CWD базової оболонки, що виконує процес Node.

Ви можете змінити поточну робочу директорію процесу Node за допомогою команди process.chdir().

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

Коли процес у вузлі існує, ви опинитесь в CWD, в якому розпочали процес.


14

Те, що ви намагаєтеся зробити, неможливо. Причиною цього є те, що в системі POSIX (Linux, OSX тощо) дочірній процес не може змінити середовище батьківського процесу. Сюди входить зміна робочого каталогу батьківського процесу та змінних середовища.

Коли ви знаходитесь у командному рядку і ви переходите до виконання сценарію Node, ваш поточний процес ( bash, zshбудь-що) породжує новий процес, у якому є власне середовище, як правило, копію вашого поточного оточення (це можливо змінити за допомогою системних викликів ; але це виходить за межі цієї відповіді), що дозволяє цьому процесу робити все, що йому потрібно зробити, у повній ізоляції. Коли підпроцес закінчується, контроль передається в оболонку, де навколишнє середовище не вплинуло.

Причин тому багато, але для однієї уявіть, що ви виконали сценарій у фоновому режимі (через ./foo.js &), і коли він запустився, він почав змінювати ваш робочий каталог або переосмислювати ваш PATH. Це був би кошмар.

Якщо вам потрібно виконати деякі дії, які потребують зміни робочого каталогу вашої оболонки, вам потрібно буде написати функцію в оболонці. Наприклад, якщо ви використовуєте Bash, ви можете помістити це у свій ~/.bash_profile:

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

і тоді це прикольна річ виконана:

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

Якщо вам потрібно зробити ще складніші речі, ви завжди можете викликати свій скрипт nodejs з цієї функції.

Це єдиний спосіб досягти того, що ви намагаєтеся зробити.


10

Коротка відповідь: немає (легкого?) Способу, але ви можете зробити щось, що відповідає вашим цілям.

Я зробив подібний інструмент (невелика команда, яка, даючи опис проекту, задає оточення, шляхи, каталоги тощо). Що я роблю, це налаштувати все, а потім покласти оболонку:

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

Після виконання, ви будете в оболонці з новим каталогом (і, в моєму випадку, середовищем). Звичайно, ви можете змінити баш на будь-яку оболонку, яка вам більше подобається. Основні відмінності від того, що ви спочатку просили:

  • Існує додатковий процес, тому ...
  • ви повинні написати "вихід", щоб повернутися, а потім ...
  • після існуючих, усі зміни скасовуються.

Однак для мене ці відмінності бажані.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.