Cambiar el directorio de trabajo en mi contexto de shell actual al ejecutar el script Node

113

Estoy tratando de cambiar el directorio de trabajo de mi script Node.js cuando se ejecuta desde un script bin. Tengo algo como lo siguiente:

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

Cuando ejecuto este archivo con ./bin/nodefile, sale, pero el directorio de trabajo del contexto de shell actual no ha cambiado. También probé shelljs , pero eso tampoco funciona.

¿Cuál es la mejor manera de hacer esto? Entiendo que está funcionando, pero es un proceso separado.

Jonovono
fuente
¿Qué pruebas tienes de que la cwd no cambió? Recuerde que las rutas utilizadas en require () y cwd son dos cosas diferentes.
jeesty
¿Hay alguna forma de hacer esto en Windows?
Phillip

Respuestas:

145

La forma correcta de cambiar de directorio es con process.chdir(directory). Aquí tienes un ejemplo de la documentación :

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

Esto también se puede probar en el REPL de Node.js:

[monitor@s2 ~]$ node
> process.cwd()
'/home/monitor'
> process.chdir('../');
undefined
> process.cwd();
'/home'
hexacianuro
fuente
¡Ups! Sí, ese es el comando que estoy usando. Sin embargo, cuando lo uso en un script simple, todavía no parece funcionar (una vez que el script sale, todavía estoy en el directorio anterior) .Si llamo a process.cwd (), dice que estoy en el directorio que debería estar, pero mi terminal si llamo a pwd dice que estoy en otra cosa. ¿Porque es un proceso diferente?
Jonovono
10
El método cambia el directorio de trabajo actual del proceso , no el shell. Hasta donde yo sé, cambiar la cwd externa de un proceso en ejecución es bastante complejo y no se recomienda. ¿Cuál es tu razón para querer hacer esto?
hexacianuro
3
Hmm. OK gracias. Bueno, la razón por la que quiero hacer esto es porque estoy creando una aplicación de terminal para organizar mis proyectos. Entonces, básicamente, quiero poder enumerar mis proyectos y cambiar fácilmente la ubicación actual del shell a eso. Ahora que lo pienso, voy a ver cómo z ( github.com/rupa/z ) hace esto. Aunque eso se hace en bash. ¿Quizás podría hacer esto en applecript?
Jonovono
@hexacyanide gracias por agregar fue molesto porque los cambios no estaban alineados
Eugen Sunic
33

No hay un método integrado para que Node cambie el CWD del shell subyacente que ejecuta el proceso de Node.

Usted puede cambiar el directorio de trabajo actual del proceso de nodo a través del comando process.chdir().

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

Cuando exista el proceso de nodo, se encontrará de nuevo en el CWD en el que inició el proceso.

tres
fuente
14

Lo que intentas hacer no es posible. La razón de esto es que en un sistema POSIX (Linux, OSX, etc.), un proceso hijo no puede modificar el entorno de un proceso padre. Esto incluye modificar el directorio de trabajo del proceso padre y las variables de entorno.

Cuando usted está en la línea de comandos y que vaya a ejecutar la secuencia de comandos de nodo, el proceso actual ( bash, zsh, lo que sea) genera un nuevo proceso que tiene su propio entorno, por lo general una copia de su entorno actual (es posible cambiar esto a través de llamadas al sistema ; pero eso está más allá del alcance de esta respuesta), lo que permite que ese proceso haga lo que necesite hacer en completo aislamiento. Cuando el subproceso sale, el control se devuelve al proceso de su shell, donde el entorno no se ha visto afectado.

Hay muchas razones para esto, pero por una, imagine que ejecutó un script en segundo plano (vía ./foo.js &) y, mientras se ejecutaba, comenzó a cambiar su directorio de trabajo o anular su archivo PATH. Eso sería una pesadilla.

Si necesita realizar algunas acciones que requieren cambiar el directorio de trabajo de su shell, necesitará escribir una función en su shell. Por ejemplo, si está ejecutando Bash, puede poner esto en su ~/.bash_profile:

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

y luego esta cosa genial es factible:

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

Si necesita hacer cosas más complejas además, siempre puede llamar a su script nodejs desde esa función.

Esta es la única forma en que puede lograr lo que está tratando de hacer.

Spike Grobstein
fuente
10

Respuesta corta: de ninguna manera (¿fácil?), Pero puede hacer algo que sirva a su propósito.

He hecho una herramienta similar (un pequeño comando que, dada una descripción de un proyecto, establece el entorno, las rutas, los directorios, etc.). Lo que hago es configurar todo y luego generar un shell con:

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

Después de la ejecución, estará en un shell con el nuevo directorio (y, en mi caso, el entorno). Por supuesto, puede cambiar bash por el shell que prefiera. Las principales diferencias con lo que solicitó originalmente son:

  • Hay un proceso adicional, así que ...
  • tienes que escribir 'salir' para volver, y luego ...
  • después de existir, todos los cambios se deshacen.

Sin embargo, para mí, las diferencias son deseables.

Evolopment
fuente