¿Cómo obtengo la ruta al script actual con Node.js?


980

¿Cómo obtendría la ruta al script en Node.js?

Sé que hay process.cwd, pero eso solo se refiere al directorio donde se llamó al script, no al script en sí. Por ejemplo, digamos que estoy /home/kyle/y ejecuto el siguiente comando:

node /home/kyle/some/dir/file.js

Si llamo process.cwd(), recibo /home/kyle/, no /home/kyle/some/dir/. ¿Hay alguna manera de obtener ese directorio?


66
nodejs.org/docs/latest/api/globals.html el enlace de documentación de la respuesta aceptada.
allenhwkim

Respuestas:


1395

Lo encontré después de revisar la documentación nuevamente. Lo que estaba buscando eran los __filenamey __dirnamelas variables de nivel de módulo.

  • __filenamees el nombre del archivo del módulo actual. Esta es la ruta absoluta resuelta del archivo del módulo actual. (ej . /home/kyle/some/dir/file.js:)
  • __dirnamees el nombre del directorio del módulo actual. (ej . /home/kyle/some/dir:)

3
Si solo desea el nombre del directorio y no la ruta completa, puede hacer algo como esto: function getCurrentDirectoryName () {var fullPath = __dirname; var ruta = fullPath.split ('/'); var cwd = ruta [ruta.length-1]; volver cwd; }
Anthony Martin

58
@AnthonyMartin __dirname.split ("/"). Pop ()
19h

66
Para aquellos que prueban la solución @apx (como lo hice :), esta solución no funciona en Windows.
Laoujin

36
O simplemente__dirname.split(path.sep).pop()
Burgi

47
Orequire('path').basename(__dirname);
Vyacheslav Cotruta

251

Entonces básicamente puedes hacer esto:

fs.readFile(path.resolve(__dirname, 'settings.json'), 'UTF-8', callback);

Use resolve () en lugar de concatenar con '/' o '\', de lo contrario, se encontrará con problemas multiplataforma.

Nota: __dirname es la ruta local del módulo o script incluido. Si está escribiendo un complemento que necesita conocer la ruta del script principal, es:

require.main.filename

o simplemente para obtener el nombre de la carpeta:

require('path').dirname(require.main.filename)

16
Si su objetivo es solo analizar e interactuar con el archivo json, a menudo puede hacerlo más fácilmente a través de var settings = require('./settings.json'). Por supuesto, es síncrono fs IO, así que no lo hagas en tiempo de ejecución, pero en el momento del inicio está bien, y una vez que esté cargado, se almacenará en caché.
isaacs

2
@Marc ¡Gracias! Por un tiempo, estaba hackeando el hecho de que __dirname es local para cada módulo. Tengo una estructura anidada en mi biblioteca y necesito saber en varios lugares la raíz de mi aplicación. Me alegro de saber cómo hacer esto ahora: D
Thijs Koerselman

Nodo V8: path.dirname (process.mainModule.filename)
wayofthefuture

Si no considera que Windows sea una plataforma real, ¿podemos omitir la resolución? BSD, Macos, linux, tizen, symbian, Solaris, android, flutter, webos todos usan / ¿verdad?
Ray Foss


119

Este comando devuelve el directorio actual:

var currentPath = process.cwd();

Por ejemplo, para usar la ruta para leer el archivo:

var fs = require('fs');
fs.readFile(process.cwd() + "\\text.txt", function(err, data)
{
    if(err)
        console.log(err)
    else
        console.log(data.toString());
});

Para aquellos que no entendieron Asíncrono y Sincrónico , vea este enlace ... stackoverflow.com/a/748235/5287072
DarckBlezzer

16
esto es exactamente lo que el OP no quiere ... ¡la solicitud es para la ruta del script ejecutable!
caesarsol

3
El directorio actual es una cosa muy diferente. Si ejecuta algo como cd /foo; node bar/test.js, el directorio actual sería /foo, pero el script se encuentra en /foo/bar/test.js.
rjmunro

No es una buena respuesta. Es un desorden lógico porque este puede ser un camino mucho más corto de lo que esperas.
kris_IV

¿Por qué harías esto? si el archivo fuera relativo al directorio actual que podría leer text.txty funcionaría, no necesita construir la ruta absoluta
Michael Mrozek,

104

Use __dirname !!

__dirname

El nombre del directorio del módulo actual. Esto es lo mismo que la ruta.dirname () del__filename .

Ejemplo: ejecutar nodo example.js desde / Users / mjr

console.log(__dirname);
// Prints: /Users/mjr
console.log(path.dirname(__filename));
// Prints: /Users/mjr

https://nodejs.org/api/modules.html#modules_dirname

Para ESModules, querrá usar: import.meta.url


1
Esto también sobrevive a los enlaces simbólicos. Entonces, si crea un bin y necesita encontrar un archivo, por ejemplo path.join (__ dirname, "../example.json"); seguirá funcionando cuando su binario esté vinculado en node_modules / .bin
Jason

2
Esta respuesta no solo se dio años antes, sino que ya no funciona con los módulos ES .
Dan Dascalescu

48

Cuando se trata del guión principal, es tan simple como:

process.argv[1]

De la documentación de Node.js :

process.argv

Una matriz que contiene los argumentos de la línea de comando. El primer elemento será 'nodo', el segundo elemento será la ruta al archivo JavaScript . Los siguientes elementos serán argumentos de línea de comando adicionales.

Si necesita conocer la ruta de un archivo de módulo, use __filename .


3
¿Podría el downvoter explicar por qué esto no se recomienda?
Tamlyn

1
@Tamlyn Quizás porque se process.argv[1]aplica solo al script principal mientras __filenameseñala el archivo del módulo que se está ejecutando. Actualizo mi respuesta para enfatizar la diferencia. Aún así, no veo nada malo en usar process.argv[1]. Depende de los requisitos de uno.
Lukasz Wiktor

10
Si el script principal se lanzó con un administrador de procesos de nodo como pm2 process.argv [1] apuntará al ejecutable del administrador de procesos /usr/local/lib/node_modules/pm2/lib/ProcessContainerFork.js
user3002996

34

Node.js 10 admite módulos ECMAScript , donde __dirnamey __filenameya no están disponibles .

Luego, para obtener la ruta al módulo ES actual, uno debe usar:

import { fileURLToPath } from 'url';

const __filename = fileURLToPath(import.meta.url);

Y para el directorio que contiene el módulo actual:

import { dirname } from 'path';
import { fileURLToPath } from 'url';

const __dirname = dirname(fileURLToPath(import.meta.url));

¿Cómo sabría si estoy escribiendo un módulo ES o no? ¿Es solo una cuestión de qué versión de Nodo estoy ejecutando, o si estoy usando palabras clave de importación / exportación?
Ed Brannin

2
Módulos ES disponibles solo con --experimental-modulesbandera.
Nickensoul

1
--experimental-modules solo es necesario si está ejecutando la versión del nodo es <13.2. solo nombra el archivo .mjs en lugar de .js
Brent



13

Sé que esto es bastante antiguo, y la pregunta original a la que respondía está marcada como duplicada y dirigida aquí, pero me encontré con un problema tratando de hacer que los reporteros de jazmín trabajen y no me gustó la idea de que tuve que degradar Para que funcione. Descubrí que jasmine-reporters no estaba resolviendo el savePath correctamente y en realidad estaba poniendo la salida de la carpeta de informes en el directorio jasmine-reporters en lugar del directorio raíz de donde ejecuté gulp. Para que esto funcione correctamente, terminé usando process.env.INIT_CWD para obtener el Directorio de trabajo actual inicial, que debería ser el directorio donde ejecutó gulp. Espero que esto ayude a alguien.

var reporters = require('jasmine-reporters');
var junitReporter = new reporters.JUnitXmlReporter({
  savePath: process.env.INIT_CWD + '/report/e2e/',
  consolidateAll: true,
  captureStdout: true
 });

8

Puede usar process.env.PWD para obtener la ruta actual de la carpeta de la aplicación.


2
OP solicita la "ruta de acceso al script" solicitada. PWD, que significa algo así como Process Working Directory, no es eso. Además, la redacción de la "aplicación actual" es engañosa.
dmcontador

7

Si está utilizando pkgpara empaquetar su aplicación, encontrará útil esta expresión:

appDirectory = require('path').dirname(process.pkg ? process.execPath : (require.main ? require.main.filename : process.argv[0]));
  • process.pkgindica si la aplicación ha sido empaquetada por pkg.

  • process.execPathcontiene la ruta completa del ejecutable, que es /usr/bin/nodeo similar para las invocaciones directas de scripts ( node test.js), o la aplicación empaquetada.

  • require.main.filename contiene la ruta completa del script principal, pero está vacía cuando Node se ejecuta en modo interactivo.

  • __dirnamemantiene la ruta completa de la secuencia de comandos actual , por lo que no la estoy usando (aunque puede ser lo que OP pide; entonces mejor usarlo, appDirectory = process.pkg ? require('path').dirname(process.execPath) : (__dirname || require('path').dirname(process.argv[0]));notando que en modo interactivo __dirnameestá vacío.

  • Para el modo interactivo, use process.argv[0]para obtener la ruta al Nodo ejecutable o process.cwd()para obtener el directorio actual.


3

Use el basenamemétodo del pathmódulo:

var path = require('path');
var filename = path.basename(__filename);
console.log(filename);

Aquí está la documentación de la que se tomó el ejemplo anterior.

Como Dan señaló, Node está trabajando en módulos ECMAScript con el indicador "--experimental-modules". El nodo 12 todavía es compatible __dirnamey__filename como el anterior.


Si está utilizando la --experimental-modulesbandera, hay un enfoque alternativo .

La alternativa es obtener la ruta al módulo ES actual :

const __filename = new URL(import.meta.url).pathname;

Y para el directorio que contiene el módulo actual:

import path from 'path';

const __dirname = path.dirname(new URL(import.meta.url).pathname);

-2

Si desea algo más como $ 0 en un script de shell, intente esto:

var path = require('path');

var command = getCurrentScriptPath();

console.log(`Usage: ${command} <foo> <bar>`);

function getCurrentScriptPath () {
    // Relative path from current working directory to the location of this script
    var pathToScript = path.relative(process.cwd(), __filename);

    // Check if current working dir is the same as the script
    if (process.cwd() === __dirname) {
        // E.g. "./foobar.js"
        return '.' + path.sep + pathToScript;
    } else {
        // E.g. "foo/bar/baz.js"
        return pathToScript;
    }
}

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.