206

From the node manual I see that I can get the directory of a file with __dirname, but from the REPL this seems to be undefined. Is this a misunderstanding on my side or where is the error?

$ node
> console.log(__dirname)
ReferenceError: __dirname is not defined
    at repl:1:14
    at REPLServer.eval (repl.js:80:21)
    at Interface.<anonymous> (repl.js:182:12)
    at Interface.emit (events.js:67:17)
    at Interface._onLine (readline.js:162:10)
    at Interface._line (readline.js:426:8)
    at Interface._ttyWrite (readline.js:603:14)
    at ReadStream.<anonymous> (readline.js:82:12)
    at ReadStream.emit (events.js:88:20)
    at ReadStream._emitKey (tty.js:320:10)
Flip
  • 5,443
  • 6
  • 39
  • 69
topskip
  • 14,586
  • 14
  • 65
  • 92
  • 28
    `__dirname` and `__filename` are also [not available when `node` is called with the `--experimental-modules` flag](https://stackoverflow.com/questions/46745014/alternative-for-dirname-in-node-when-using-the-experimental-modules-flag). – Dan Dascalescu Dec 18 '18 at 05:17
  • 2
    I got this issue when using eslint, I had mistakenly set `"browser": true` instead of `"node": true` in my .eslintrc.json file. – Toivo Säwén Mar 25 '20 at 16:37
  • If nothing works here's a hack https://stackoverflow.com/a/49879107/696535 – Pawel Jul 17 '21 at 10:25

11 Answers11

224

__dirname is only defined in scripts. It's not available in REPL.

try make a script a.js

console.log(__dirname);

and run it:

node a.js

you will see __dirname printed.

Added background explanation: __dirname means 'The directory of this script'. In REPL, you don't have a script. Hence, __dirname would not have any real meaning.

Yaakov Belch
  • 4,413
  • 30
  • 38
qiao
  • 17,202
  • 5
  • 56
  • 46
143

Building on the existing answers here, you could define this in your REPL:

__dirname = path.resolve(path.dirname(''));

Or:

__dirname = path.resolve();

If no path segments are passed, path.resolve() will return the absolute path of the current working directory.


Or @Jthorpe's alternatives:

__dirname = process.cwd();
__dirname = fs.realpathSync('.');
__dirname = process.env.PWD
c24w
  • 6,813
  • 6
  • 37
  • 47
  • if you use `nesh` you can define this as part of your load script; it's nifty – jcollum Nov 18 '15 at 21:15
  • 2
    or `__dirname = process.cwd()` or `__dirname=fs.realpathSync('.')` or `__dirname = process.env.PWD` – Jthorpe Apr 06 '16 at 04:31
  • 1
    `path.dirname` seems to not accept non-string values anymore in the newest major version, `6.0.0`, so the first suggestion in this answer will not work. – trysis Jun 16 '16 at 15:22
141

If you are using Node.js modules, __dirname and __filename don't exist.

From the Node.js documentation:

No require, exports, module.exports, __filename, __dirname

These CommonJS variables are not available in ES modules.

require can be imported into an ES module using module.createRequire().

Equivalents of __filename and __dirname can be created inside of each file via import.meta.url:

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

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

https://nodejs.org/docs/latest-v15.x/api/esm.html#esm_no_filename_or_dirname

advaiyalad
  • 90
  • 10
AMS777
  • 2,761
  • 1
  • 15
  • 21
  • 29
    Technically this is the only correct answer here. All of the other solutions use the current working directory. Which is different from the __dirname feature that is really the folder holding the currently running script. – Ravi Luthra Sep 04 '20 at 20:19
  • 4
    This is the perfect answer for this exact question. Thank you, it helped me a lot! @RaviLuthra is 100% correct. – Karlsson Dec 29 '20 at 08:53
  • 3
    Concurr this is the only correct answer here "if" problem is relating to ES6 modules type of architecture. Import statement needs to reference path that evetnually gets passed downt to __dirname which is the feature that is really the folder holding the currently running script. – – Bruno Miyamotto Luque Dec 30 '20 at 18:45
  • Obviously `import.meta.url` is `undefined` when `cat script.js | node --input-type module` – Saber Hayati May 21 '22 at 15:42
58

In ES6 use:

import path from 'path';
const __dirname = path.resolve();

also available when node is called with --experimental-modules

t-reksio
  • 2,593
  • 16
  • 12
10

-> At ES6 version use :

import path from "path"
const __dirname = path.resolve();

-> And use it like this for example:

res.sendFile(path.join(__dirname ,'views','shop.html'))
myeongkil kim
  • 2,268
  • 4
  • 14
  • 20
AlexD
  • 143
  • 1
  • 4
  • 4
    This is **NOT** equivalent to `__dirname` but rather `process.cwd()`. For example, you will get different results when running the script from different directories. When using ESM a better approach is to use `import.meta.url`. See https://nodejs.org/docs/latest-v14.x/api/esm.html#esm_import_meta and https://stackoverflow.com/questions/46745014/alternative-for-dirname-in-node-when-using-the-experimental-modules-flag – jacobq May 21 '21 at 17:12
8

As @qiao said, you can't use __dirname in the node repl. However, if you need need this value in the console, you can use path.resolve() or path.dirname(). Although, path.dirname() will just give you a "." so, probably not that helpful. Be sure to require('path').

jeremywoertink
  • 2,143
  • 1
  • 22
  • 28
8

I was also trying to join my path using path.join(__dirname, 'access.log') but it was throwing the same error.

Here is how I fixed it:

I first imported the path package and declared a variable named __dirname, then called the resolve path method.

In CommonJS

var path = require("path");

var __dirname = path.resolve();

In ES6+

import path  from 'path';

const __dirname = path.resolve();

Happy coding.......

abdul-wahab
  • 2,056
  • 2
  • 19
  • 35
Desire Kaleba
  • 1,118
  • 10
  • 11
  • I am on node v15.3.0 and I do not need to use `path.resolve()`. `__dirname` just works out of the box. Is your answer still relevant to ES6+? – Zac Dec 02 '20 at 22:00
  • @Zac __dirname is only available on Node 14 or higher if you are using CommonJS. But ECMA is pushing towards ES modules being the standard instead of CommonJS. – Juha Untinen Nov 26 '21 at 11:42
4

If you got node __dirname not defined with node --experimental-modules, you can do :

const __dirname = path.dirname(import.meta.url)
                      .replace(/^file:\/\/\//, '') // can be usefull

Because othe example, work only with current/pwd directory not other directory.

Sky Voyager
  • 11,413
  • 4
  • 45
  • 70
3

Seems like you could also do this:

__dirname=fs.realpathSync('.');

of course, dont forget fs=require('fs')

(it's not really global in node scripts exactly, its just defined on the module level)

  • 1
    You don't need to require core modules in the REPL; it will load them on the fly for you. – c24w Oct 31 '19 at 12:14
3

I was running a script from batch file as SYSTEM user and all variables like process.cwd() , path.resolve() and all other methods would give me path to C:\Windows\System32 folder instead of actual path. During experiments I noticed that when an error is thrown the stack contains a true path to the node file.

Here's a very hacky way to get true path by triggering an error and extracting path from e.stack. Do not use.

// this should be the name of currently executed file
const currentFilename = 'index.js';

function veryHackyGetFolder() {
  try {
    throw new Error();
  } catch(e) {
    const fullMsg = e.stack.toString();
    const beginning = fullMsg.indexOf('file:///') + 8;
    const end = fullMsg.indexOf('\/' + currentFilename);
    const dir = fullMsg.substr(beginning, end - beginning).replace(/\//g, '\\');
    return dir;
  }
}

Usage

const dir = veryHackyGetFolder();
Pawel
  • 13,032
  • 4
  • 61
  • 66
  • If you're not running this through the REPL, you _can_ use `__dirname` and `__filename`. – c24w Nov 12 '19 at 10:48
  • 1
    This is the only answer that at least tries to provide correct solution. – Tomáš Zato - Reinstate Monica Jun 10 '20 at 11:21
  • @c24w I tried __dirname, __filename and everything else. No standard solution worked in my case. Here's my project which runs a process as SYSTEM from task scheduler if you're bored github.com/DVLP/Unscheduler. Any standard solution that otherwise works is obviously better than my hack above :) – Pawel Jun 15 '20 at 13:10
1

Though its not the solution to this problem I would like to add it as it may help others.

You should have two underscores before dirname, not one underscore (__dirname not _dirname).

NodeJS Docs

surj
  • 4,488
  • 2
  • 21
  • 30
Siva Prakash
  • 4,322
  • 32
  • 26