What is the difference between __dirname and ./ in node.js?
Solution 1:
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.
Solution 2:
./
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.