Измените рабочий каталог в моем текущем контексте оболочки при запуске Node script

114

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

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

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

Как лучше всего это сделать? Я понимаю, что это работает, но это отдельный процесс.

Йоновоно
источник
какие у вас доказательства того, что cwd не менялся? Помните, что пути, используемые в require () и 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'
hexacyanide
источник
К сожалению. Я действительно использую эту команду. Однако, когда я использую его в простом скрипте, он все равно не работает (после выхода из скрипта я все еще в старом каталоге). Если я вызываю process.cwd (), он говорит, что я нахожусь в каталоге, в котором должен быть, но терминал, если я вызываю pwd, говорит, что я в другом месте. Потому что это другой процесс?
Jonovono
10
Метод изменяет текущий рабочий каталог процесса , а не оболочку. Насколько мне известно, изменение внешнего cwd запущенного процесса довольно сложно и не рекомендуется. В чем причина вашего желания это сделать?
hexacyanide
3
Хм. Хорошо, спасибо. Причина, по которой я хочу это сделать, заключается в том, что я делаю терминальное приложение для организации своих проектов. Итак, в основном я хочу иметь возможность перечислять свои проекты и легко менять текущее местоположение оболочки на это. Теперь, когда я об этом подумал, я собираюсь изучить, как z ( github.com/rupa/z ) это делает. Хотя это делается в bash. Я мог бы сделать это в applescript?
Jonovono
@hexacyanide спасибо за добавление беспокоило, потому что изменения не были согласованы
Евгений Суник
33

У Node нет встроенного метода для изменения CWD базовой оболочки, запускающей процесс Node.

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

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

Когда процесс Node существует, вы снова окажетесь в CWD, в котором начали процесс.

dthree
источник
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'
});

После выполнения вы окажетесь в оболочке с новым каталогом (и, в моем случае, средой). Конечно, вы можете изменить bash для любой оболочки, которую предпочитаете. Основные отличия от того, о чем вы изначально просили:

  • Есть дополнительный процесс, так что ...
  • вы должны написать «выход», чтобы вернуться, а затем ...
  • после создания все изменения отменяются.

Однако для меня такие различия желательны.

Развитие
источник