588

When programming in Node.js and referencing files that are located somewhere in relation to your current directory, is there any reason to use the __dirname variable instead of just a regular ./? I've been using ./ thus far in my code and just discovered the existence of __dirname, and essentially want to know whether it would be smart to convert my ./'s to that, and if so, why that would be a smart idea.

Yi Jiang
  • 49,435
  • 16
  • 136
  • 136
thisissami
  • 15,445
  • 16
  • 47
  • 74
  • 65
    tl;dr: So, basically, the difference is that './' and 'process.cwd()' refer to the current dir of the terminal calling the script, whereas the '__dirname' refers to the dir in which the script is stored. – Gui Imamura Oct 18 '14 at 00:02
  • 9
    _Except_ when `.` is used inside `require`. The path inside `require` is always relative to the file containing the call to `require`. – Govind Rai May 14 '19 at 00:17

2 Answers2

942

The gist

In Node.js, __dirname is always the directory in which the currently executing script resides (see this). So if you typed __dirname into /d1/d2/myscript.js, the value would be /d1/d2.

By contrast, . gives you the directory from which you ran the node command in your terminal window (i.e. your working directory) when you use libraries like path and fs. Technically, it starts out as your working directory but can be changed using process.chdir().

The exception is when you use . with require(). The path inside require is always relative to the file containing the call to require.

For example...

Let's say your directory structure is

/dir1
  /dir2
    pathtest.js

and pathtest.js contains

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

and you do

cd /dir1/dir2
node pathtest.js

you get

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

Your working directory is /dir1/dir2 so that's what . resolves to. Since pathtest.js is located in /dir1/dir2 that's what __dirname resolves to as well.

However, if you run the script from /dir1

cd /dir1
node dir2/pathtest.js

you get

. = /dir1
__dirname = /dir1/dir2

In that case, your working directory was /dir1 so that's what . resolved to, but __dirname still resolves to /dir1/dir2.

Using . inside require...

If inside dir2/pathtest.js you have a require call into include a file inside dir1 you would always do

require('../thefile')

because the path inside require is always relative to the file in which you are calling it. It has nothing to do with your working directory.

Community
  • 1
  • 1
d512
  • 32,267
  • 28
  • 81
  • 107
  • 6
    I agree. I will change the accepted answer. Please keep in mind that this answer was added 2.5 years after the original one was accepted, and I only just noticed it now (another 2 years later). :) Better late than never! – thisissami Apr 30 '15 at 17:19
  • 17
    It's worth noting that `./` is not *always* the directory that node was launched from. It starts out that way, but can be changed via `process.chdir()`. So, `./` is always the current working directory, which is usually the directory node was launched from, unless your code explicitly changed the working directory. – gilly3 Jun 04 '15 at 20:32
  • 3
    I am a little confuse about the Using . inside require part, if the path inside require is always relative to the file you are calling, isn't the path should be require('../thefile') instead of require('../dir1/thefile')? i thought the .. bring the current position of the path back one level from dir2 to dir1 already. Do you still need to put dir1 in the path or am i miss understood something? – andromada Apr 07 '17 at 03:13
  • 1
    And how would you do if you need to use `../someDir` in some script and you're going to run the command from a different folder? – cbdeveloper Nov 05 '19 at 15:29
  • A note that with ES modules, the `__dirname` global is gone but can be replaced by `import { dirname } from "path";` – Robin Métral Oct 23 '21 at 05:10
161

./ refers to the current working directory, except in the require() function. When using require(), it translates ./ to the directory of the current file called. __dirname is always the directory of the current file.

For example, with the following file structure

/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'));

If I cd into /home/user/dir and run node dir.js I will get

{ hello: 'world' }
text file

But when I run the same script from /home/user/ I get

{ 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)

Using ./ worked with require but not for fs.readFileSync. That's because for fs.readFileSync, ./ translates into the cwd (in this case /home/user/). And /home/user/files/somefile.txt does not exist.

Timo Tijhof
  • 10,032
  • 6
  • 34
  • 48
fent
  • 17,861
  • 15
  • 87
  • 91
  • oh i thought __dirname was the current working directory... thanks for the clarification! – thisissami Nov 15 '11 at 21:47
  • 1
    Is there any way to reference the working directory of the app with fs? For example, I'm trying to load a file from the working directory `/movies`, but since my module is in a file `/custom_modules/`, `__dirname` tries to grab the movie from , `/custom_modules/movies` –  Jul 24 '14 at 13:32
  • 4
    You can use `./` or `process.cwd()`. see http://nodejs.org/api/process.html#process_process_cwd – fent Jul 24 '14 at 17:14
  • Worth noting it is _not_ a good idea to use __dirname over ./ in require statements because although they behave identically in node, it can cause issues with browserify builds for packages that are easily otherwise avoided. – Jed Watson Apr 23 '15 at 13:17