¿Cuál es la diferencia entre __dirname y ./ en node.js?


498

Al programar en Node.js y hacer referencia a archivos que se encuentran en algún lugar en relación con su directorio actual, ¿hay alguna razón para usar la __dirnamevariable en lugar de solo una regular ./? He estado usando ./ hasta ahora en mi código y acabo de descubrir la existencia de __dirname, y esencialmente quiero saber si sería inteligente convertir mis ./ a eso, y si es así, ¿por qué sería una idea inteligente? .


47
tl; dr: Entonces, básicamente, la diferencia es que './' y 'process.cwd ()' se refieren al directorio actual del terminal que llama al script, mientras que '__dirname' se refiere al directorio en el que se encuentra el script almacenado
Gui Imamura

1
Excepto cuando .se usa en el interior require. La ruta interna requiresiempre es relativa al archivo que contiene la llamada a require.
Govind Rai

Respuestas:


814

La esencia

En Node.js, __dirnamees siempre el directorio en el que reside el script que se está ejecutando actualmente ( consulte esto ). Así que si ha escrito __dirnameen /d1/d2/myscript.js, el valor sería /d1/d2.

Por el contrario, .le proporciona el directorio desde el que ejecutó el nodecomando en la ventana de su terminal (es decir, su directorio de trabajo) cuando utiliza bibliotecas como pathy fs. Técnicamente, comienza como su directorio de trabajo pero se puede cambiar usando process.chdir().

La excepción es cuando usas .con require(). La ruta interna requiresiempre es relativa al archivo que contiene la llamada a require.

Por ejemplo...

Digamos que su estructura de directorio es

/dir1
  /dir2
    pathtest.js

y pathtest.jscontiene

var path = require("path");
console.log(". = %s", path.resolve("."));
console.log("__dirname = %s", path.resolve(__dirname));

y lo hace

cd /dir1/dir2
node pathtest.js

usted obtiene

. = /dir1/dir2
__dirname = /dir1/dir2

Su directorio de trabajo es /dir1/dir2así que eso es lo que .resuelve. Como pathtest.jsse encuentra en /dir1/dir2eso, eso también se __dirnameresuelve.

Sin embargo, si ejecuta el script desde /dir1

cd /dir1
node dir2/pathtest.js

usted obtiene

. = /dir1
__dirname = /dir1/dir2

En ese caso, su directorio de trabajo fue /dir1lo que .resolvió, pero __dirnameaún lo resuelve /dir1/dir2.

Usando .dentro require...

Si dentro dir2/pathtest.jstiene una requirellamada para incluir un archivo dentro dir1, siempre lo haría

require('../thefile')

porque la ruta dentro requiresiempre es relativa al archivo en el que lo está llamando. No tiene nada que ver con su directorio de trabajo.


38
En mi opinión, esta explicación es un poco más clara que la de la respuesta aceptada (ya sabes, "el directorio actual" es un poco ambiguo allí).
Encarnado el

55
Estoy de acuerdo. Cambiaré la respuesta aceptada. Tenga en cuenta que esta respuesta se agregó 2.5 años después de que se aceptara la original, y solo la noté ahora (otros 2 años después). :) ¡Mejor tarde que nunca!
thisissami

14
Vale la pena señalar que ./no siempre es el directorio desde el que se inició el nodo. Comienza de esa manera, pero se puede cambiar a través de process.chdir(). Entonces, ./siempre es el directorio de trabajo actual, que generalmente es el nodo de directorio desde el que se inició, a menos que su código haya cambiado explícitamente el directorio de trabajo.
gilly3

3
Estoy un poco confundido sobre el uso. inside require part, si la ruta inside require siempre es relativa al archivo que está llamando, ¿no debería ser la ruta require ('../ thefile') en lugar de require ('../ dir1 / thefile')? pensé que ... traer la posición actual de la ruta de nuevo un nivel de dir2 a dir1 ya. ¿Todavía necesitas poner dir1 en la ruta o no entiendo algo?
andromada

1
¿Y cómo lo haría si necesita usar ../someDiralgún script y va a ejecutar el comando desde una carpeta diferente?
cbdeveloper el

154

./se refiere al directorio de trabajo actual, excepto en la require()función. Cuando se usa require(), se traduce ./al directorio del archivo actual llamado. __dirnamees siempre el directorio del archivo actual.

Por ejemplo, con la siguiente estructura de archivos

/home/user/dir/files/config.json

{
  "hello": "world"
}

/home/user/dir/files/somefile.txt

text file

/home/user/dir/dir.js

var fs = require('fs');

console.log(require('./files/config.json'));
console.log(fs.readFileSync('./files/somefile.txt', 'utf8'));

Si cdentro /home/user/diry corro node dir.jsobtendré

{ hello: 'world' }
text file

Pero cuando ejecuto el mismo script /home/user/, obtengo

{ hello: 'world' }

Error: ENOENT, no such file or directory './files/somefile.txt'
    at Object.openSync (fs.js:228:18)
    at Object.readFileSync (fs.js:119:15)
    at Object.<anonymous> (/home/user/dir/dir.js:4:16)
    at Module._compile (module.js:432:26)
    at Object..js (module.js:450:10)
    at Module.load (module.js:351:31)
    at Function._load (module.js:310:12)
    at Array.0 (module.js:470:10)
    at EventEmitter._tickCallback (node.js:192:40)

Uso ./trabajado con requirepero no para fs.readFileSync. Eso es porque fs.readFileSync, se ./traduce en el cwd (en este caso /home/user/). Y /home/user/files/somefile.txtno existe.


oh, pensé que __dirname era el directorio de trabajo actual ... ¡gracias por la aclaración!
thisissami

¿Hay alguna forma de hacer referencia al directorio de trabajo de la aplicación con fs? Por ejemplo, estoy tratando de cargar un archivo desde el directorio de trabajo /movies, pero dado que mi módulo está en un archivo /custom_modules/, __dirnametrata de tomar la película de,/custom_modules/movies

2
Puedes usar ./o process.cwd(). ver nodejs.org/api/process.html#process_process_cwd
Fent

Vale la pena señalar que no es una buena idea usar __dirname sobre ./ en las declaraciones require porque aunque se comportan de manera idéntica en el nodo, puede causar problemas con las compilaciones de browserify para paquetes que de otro modo se evitarían fácilmente.
Jed Watson el
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.