1332

How would I get the path to the script in Node.js?

I know there's process.cwd, but that only refers to the directory where the script was called, not of the script itself. For instance, say I'm in /home/kyle/ and I run the following command:

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

If I call process.cwd(), I get /home/kyle/, not /home/kyle/some/dir/. Is there a way to get that directory?

2

15 Answers 15

1761

I found it after looking through the documentation again. What I was looking for were the __filename and __dirname module-level variables.

  • __filename is the file name of the current module. This is the resolved absolute path of the current module file. (ex:/home/kyle/some/dir/file.js)
  • __dirname is the directory name of the current module. (ex:/home/kyle/some/dir)
11
  • 71
    @AnthonyMartin __dirname.split("/").pop()
    – 19h
    Commented Mar 30, 2014 at 20:13
  • 7
    For those trying @apx solution (like I did:), this solution does not work on Windows.
    – Laoujin
    Commented May 7, 2015 at 19:33
  • 50
    Or simply __dirname.split(path.sep).pop()
    – Burgi
    Commented Jun 11, 2015 at 10:53
  • 64
    Or require('path').basename(__dirname); Commented Oct 5, 2015 at 9:03
  • 14
    This no longer works with ES modules. Commented Apr 25, 2019 at 0:38
320

So basically you can do this:

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

Use resolve() instead of concatenating with '/' or '\' else you will run into cross-platform issues.

Note: __dirname is the local path of the module or included script. If you are writing a plugin which needs to know the path of the main script it is:

require.main.filename

or, to just get the folder name:

require('path').dirname(require.main.filename)
8
  • 17
    If your goal is just to parse and interact with the json file, you can often do this more easily via var settings = require('./settings.json'). Of course, it's synchronous fs IO, so don't do it at run-time, but at startup time it's fine, and once it's loaded, it'll be cached.
    – isaacs
    Commented May 9, 2012 at 18:26
  • 3
    @Marc Thanks! For a while now I was hacking my way around the fact that __dirname is local to each module. I have a nested structure in my library and need to know in several places the root of my app. Glad I know how to do this now :D Commented Feb 28, 2013 at 14:34
  • Node V8: path.dirname(process.mainModule.filename) Commented Aug 26, 2017 at 11:47
  • 3
    This no longer works with ES modules. Commented Apr 25, 2019 at 0:38
  • @RayFoss be careful in general with string operations on directory separators, there can be surprises in both parsing and concatenation; I think most operating systems tolerate excessive slashes (e.g., //////home//////yourname/////// is a valid path), but irresponsible use of concatenation can make something that really is unreadable in some cases if you make assumptions about whether a path will have an ending slash or not, or if a slash accidentally gets appended to a file name like /home/yourname/yourfile.png/
    – jrh
    Commented May 16, 2019 at 18:40
203

Node.js 10 supports ECMAScript modules, where __dirname and __filename are no longer available.

Then to get the path to the current ES module one has to use:

import { fileURLToPath } from 'url';

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

And for the directory containing the current module:

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

const __dirname = dirname(fileURLToPath(import.meta.url));
7
  • How would I know if I'm writing an ES module or not? Is it just a matter of which Node version I'm running, or if I'm using import/export keywords?
    – Ed Brannin
    Commented Apr 18, 2019 at 19:42
  • 3
    ES modules available only with --experimental-modules flag.
    – Nickensoul
    Commented May 7, 2019 at 16:01
  • 5
    --experimental-modules is only required if you are running node version is < 13.2. just name the file .mjs rather than .js
    – Brent
    Commented Apr 12, 2020 at 19:56
  • 2
    Yes this works. @Nickensoul or in package.json "type": "module", Commented May 12, 2021 at 13:34
  • Warning, if you are using a bundler, this is the path to the source file. If you build and deploy to a different folder, it is still the path to the original source file.
    – Dirigible
    Commented Dec 27, 2022 at 17:31
171

Use __dirname!!

__dirname

The directory name of the current module. This is the same as the path.dirname() of the __filename.

Example: running node example.js from /Users/mjr

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

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

For ESModules you would want to use: import.meta.url

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

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

console.log(__dirname);
// Prints: the directory of the current module
console.log(path.dirname(__filename));
// Prints: the directory of the current module, same as __dirname
3
  • 2
    This survives symlinks too. So if you create a bin and need to find a file, eg path.join(__dirname, "../example.json"); it will still work when your binary is linked in node_modules/.bin
    – Jason
    Commented Apr 17, 2018 at 17:12
  • 7
    Not only was this answer given years earlier, it also no longer works with ES modules. Commented Apr 25, 2019 at 0:39
  • added examples for es modules Commented Jun 26 at 22:56
157

This command returns the current directory:

var currentPath = process.cwd();

For example, to use the path to read the file:

var fs = require('fs');
fs.readFile(process.cwd() + "\\text.txt", function(err, data)
{
    if(err)
        console.log(err)
    else
        console.log(data.toString());
});
5
  • For those who didn't understand Asynchronous and Synchronous, see this link... stackoverflow.com/a/748235/5287072 Commented Feb 3, 2017 at 17:33
  • 34
    this is exactly what the OP doesn't want... the request is for the path of the executable script!
    – caesarsol
    Commented Mar 29, 2018 at 9:10
  • 11
    Current directory is a very different thing. If you run something like cd /foo; node bar/test.js, current directory would be /foo, but the script is located in /foo/bar/test.js.
    – rjmunro
    Commented Jul 5, 2018 at 11:20
  • 2
    It's not a good answer. It's mess a logic beacauese this can be much shorter path than you expect.
    – kris_IV
    Commented Apr 9, 2019 at 11:31
  • 3
    Why would you ever do this; if the file were relative to the current directory you could just read text.txt and it would work, you don't need to construct the absolute path Commented Oct 3, 2019 at 3:40
58

When it comes to the main script it's as simple as:

process.argv[1]

From the Node.js documentation:

process.argv

An array containing the command line arguments. The first element will be 'node', the second element will be the path to the JavaScript file. The next elements will be any additional command line arguments.

If you need to know the path of a module file then use __filename.

2
  • 3
    @Tamlyn Maybe because process.argv[1] applies only to the main script while __filename points to the module file being executed. I update my answer to emphasize the difference. Still, I see nothing wrong in using process.argv[1]. Depends on one's requirements. Commented Jan 16, 2016 at 6:40
  • 15
    If main script was launched with a node process manager like pm2 process.argv[1] will point to the executable of the process manager /usr/local/lib/node_modules/pm2/lib/ProcessContainerFork.js Commented Mar 1, 2017 at 11:28
27
var settings = 
    JSON.parse(
        require('fs').readFileSync(
            require('path').resolve(
                __dirname, 
                'settings.json'),
            'utf8'));
2
20

Every Node.js program has some global variables in its environment, which represents some information about your process and one of it is __dirname.

2
20

Use the basename method of the path module:

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

Here is the documentation the above example is taken from.

As Dan pointed out, Node is working on ECMAScript modules with the "--experimental-modules" flag. Node 12 still supports __dirname and __filename as above.


If you are using the --experimental-modules flag, there is an alternative approach.

The alternative is to get the path to the current ES module:

import { fileURLToPath } from 'url';
const __filename = fileURLToPath(new URL(import.meta.url));

And for the directory containing the current module:

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

const __dirname = path.dirname(fileURLToPath(new URL(import.meta.url)));
1
  • On Windows there is a leading / in the path returned using this method.
    – Aalex Gabi
    Commented Feb 22, 2022 at 14:28
17

I know this is pretty old, and the original question I was responding to is marked as duplicate and directed here, but I ran into an issue trying to get jasmine-reporters to work and didn't like the idea that I had to downgrade in order for it to work. I found out that jasmine-reporters wasn't resolving the savePath correctly and was actually putting the reports folder output in jasmine-reporters directory instead of the root directory of where I ran gulp. In order to make this work correctly I ended up using process.env.INIT_CWD to get the initial Current Working Directory which should be the directory where you ran gulp. Hope this helps someone.

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

NodeJS exposes a global variable called __dirname.

__dirname returns the full path of the folder where the JavaScript file resides.

So, as an example, for Windows, if we create a script file with the following line:

console.log(__dirname);

And run that script using:

node ./innerFolder1/innerFolder2/innerFolder3/index.js

The output will be: C:\Users...<project-directory>\innerFolder1\innerFolder2\innerFolder3

2
  • 2
    __dirname is not defined in ES module scope Commented Apr 17, 2022 at 6:13
  • @TranQuocBao If you want to solve your error __dirname is not defined in ES module scope. Import and use the dirname() method from the path module.
    – Ronen
    Commented Nov 23, 2022 at 11:41
9

If you are using pkg to package your app, you'll find useful this expression:

appDirectory = require('path').dirname(process.pkg ? process.execPath : (require.main ? require.main.filename : process.argv[0]));
  • process.pkg tells if the app has been packaged by pkg.

  • process.execPath holds the full path of the executable, which is /usr/bin/node or similar for direct invocations of scripts (node test.js), or the packaged app.

  • require.main.filename holds the full path of the main script, but it's empty when Node runs in interactive mode.

  • __dirname holds the full path of the current script, so I'm not using it (although it may be what OP asks; then better use appDirectory = process.pkg ? require('path').dirname(process.execPath) : (__dirname || require('path').dirname(process.argv[0])); noting that in interactive mode __dirname is empty.

  • For interactive mode, use either process.argv[0] to get the path to the Node executable or process.cwd() to get the current directory.

0
8

You can use process.env.PWD to get the current app folder path.

1
  • 7
    OP asks for the requested "path to the script". PWD, which stands for something like Process Working Directory, is not that. Also, the "current app" phrasing is misleading.
    – dmcontador
    Commented Sep 8, 2017 at 6:48
1

index.js within any folder containing modules to export

const entries = {};
for (const aFile of require('fs').readdirSync(__dirname, { withFileTypes: true }).filter(ent => ent.isFile() && ent.name !== 'index.js')) {
  const [ name, suffix ] = aFile.name.split('.');
  entries[name] = require(`./${aFile.name}`);
}

module.exports = entries;

This will find all files in the root of the current directory, require and export every file present with the same export name as the filename stem.

-4

If you want something more like $0 in a shell script, try this:

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;
    }
}
1

Not the answer you're looking for? Browse other questions tagged or ask your own question.