Determine el directorio de trabajo de la línea de comandos al ejecutar el script bin del nodo

120

Estoy creando una interfaz de línea de comandos de nodo. Se instala globalmente y utiliza un archivo bin para ejecutarse.

Planeo tener una ventana de comando abierta en el directorio raíz de los archivos en los que estoy trabajando y luego simplemente ejecutar el comando, sin embargo, no he podido determinar el directorio de trabajo actual, ya que process.cwd()está devolviendo el directorio del paquete de nodo. Inicialmente asumí que, dado que el código se está ejecutando usando un archivo por lotes como contenedor (así es como los archivos bin pueden ejecutarse sin nodo al principio), entonces es imposible, pero coffee-script logra hacerlo. Eché un vistazo a la fuente del script de café pero no pude seguirla (no tengo suficiente experiencia).

Para probarlo usted mismo, cree un paquete con este archivo package.json:

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

este archivo de paquete de prueba en 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');

¿Alguien podría arrojar algo de luz sobre esto?

y luego intente obtener el directorio de la línea de comandos dentro de lib / test.

Daniel Chatfield
fuente

Respuestas:

196
  • process.cwd() devuelve el directorio donde se ha ejecutado el comando (no el directorio del paquete del nodo) si no ha sido cambiado por 'process.chdir' dentro de la aplicación.
  • __filename devuelve la ruta absoluta al archivo donde se coloca.
  • __dirnamedevuelve la ruta absoluta al directorio de __filename.

Si necesita cargar archivos desde el directorio de su módulo, debe usar rutas relativas.

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

en vez de

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

require(lib + '/test');

Siempre es relativo al archivo desde el que se llamó y no depende del directorio de trabajo actual.

Vadim Baryshev
fuente
2
Después process.chdir(), ¿hay alguna forma de obtener el original?
reergymerej
@reergymerej Probablemente querrá almacenar cwd primero antes de ejecutar chdir () (por ejemplo, var originalCwd = process.cwd();luego ejecute su process.chdir(), y luego podrá volver al original).
Swivel
es ../lib/testportátil?
Sebastian
No. No es una solución portátil porque Windows usa barras invertidas. Entonces, si intenta ejecutarlo en Windows, no funcionará.
zachdyer
1
En realidad, para NodeJS esto es lo mismo. Incluso en Windows puede requerir convenientemente rutas relativas a la manera de Unix. Entonces ../lib/testes portátil, mientras que la contraparte de Windows ..\lib\testno es ...
Christian Ulbrich
48

Directorio de trabajo actual

Para obtener el directorio de trabajo actual, puede usar:

process.cwd()

Sin embargo, tenga en cuenta que algunos scripts, en particular gulp, cambiarán el directorio de trabajo actual con process.chdir().

Ruta del módulo de nodo

Puede obtener la ruta del módulo actual con:

  • __filename
  • __dirname

Directorio original (donde se inició el comando)

Si está ejecutando un script desde la línea de comandos y desea el directorio original desde el que se ejecutó el script, independientemente del directorio en el que esté operando actualmente, puede utilizar:

process.env.INIT_CWD

Directorio original, cuando se trabaja con scripts NPM

A veces es deseable ejecutar un script NPM en el directorio actual, en lugar de la raíz del proyecto.

Esta variable está disponible dentro de los scripts del paquete npm como:

$INIT_CWD.

Debe ejecutar una versión reciente de NPM. Si esta variable no está disponible, asegúrese de que NPM esté actualizado.

Esto le permitirá acceder a la ruta actual en su package.json, por ejemplo:

scripts: {
  "customScript": "gulp customScript --path $INIT_CWD"
}
superluminario
fuente
process.env.INIT_CWDdevuelve el directorio depackage.json
vaughan
2
Cuidado, $ INIT_CWD solo funciona en Linux. Para Windows, deberá usar% INIT_CWD%. Creo que este problema se puede solucionar usando npmjs.com/package/cross-env , pero no lo he probado yo mismo
Stephanie
3

Alternativamente, si desea obtener únicamente el directorio actual del script NodeJS actual, puede intentar algo simple como esto. Tenga en cuenta que esto no funcionará en la CLI de nodo en sí:

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);
Juan Pablo Barbagallo
fuente
3

path.resolve('.')También es una opción confiable y limpia, porque casi siempre require('path'). Le dará la ruta absoluta del directorio desde donde se llama.

sziraqui
fuente
0

Esto es lo que funcionó para mí:

console.log(process.mainModule.filename);
Etienne Martín
fuente