159

I am creating a node command line interface. It is installed globally and uses a bin file to execute.

I plan to have a command window open at the root directory of the files I am working on and then just run the command however I have been unable to determine the current working directory as process.cwd() is returning the directory of the node package. I initially assumed that since the code is being executed using a batch file as a wrapper (that is how bin files can execute without node at the beginning) then it is impossible but coffee-script manages to do it. I took a look at the coffee-script source but couldn't follow it (not experienced enough).

To test it for yourself create a package with this package.json file:

{
  "name": "test-package",
  "version": "1.0.0",
  "bin": {
    "test-package":  "./bin/test-package"
  },
  "main": "/lib/test"
}

this test-package file in bin:

#!/usr/bin/env node

var path = require('path');
var fs   = require('fs');
var lib  = path.join(path.dirname(fs.realpathSync(__filename)), '../lib');

require(lib + '/test');

Could anyone shed some light onto this.

and then try and get the command line directory inside lib/test.

Eliran Malka
  • 15,821
  • 6
  • 77
  • 100
Daniel Chatfield
  • 2,952
  • 3
  • 19
  • 17

6 Answers6

236
  • process.cwd() returns directory where command has been executed (not directory of the node package) if it's has not been changed by 'process.chdir' inside of application.
  • __filename returns absolute path to file where it is placed.
  • __dirname returns absolute path to directory of __filename.

If you need to load files from your module directory you need to use relative paths.

require('../lib/test');

instead of

var lib  = path.join(path.dirname(fs.realpathSync(__filename)), '../lib');

require(lib + '/test');

It's always relative to file where it called from and don't depend on current work dir.

Vadim Baryshev
  • 25,689
  • 4
  • 56
  • 48
  • 3
    After `process.chdir()`, is there any way to get the original? – reergymerej Jul 16 '15 at 15:56
  • @reergymerej You'll probably want to store cwd first before executing chdir() (e.g., `var originalCwd = process.cwd();` then execute your `process.chdir()`, and you can return to the original afterwards). – Swivel Aug 16 '16 at 21:11
  • is `../lib/test` portable? – Sebastian Jun 26 '17 at 20:42
  • No. It is not a portable solution because windows uses backslashes. So if you try to run it in windows it won't work. – zachdyer Sep 14 '18 at 15:43
  • 2
    Actually for NodeJS this is all the same. Even on Windows you can conveniently require relative paths in the Unix way. So `../lib/test` is portable, whereas the Windows counterpart `..\lib\test` is not... – Christian Ulbrich Sep 26 '19 at 18:39
  • @zachdyer Windows has always used both / and \ as separators. There are some Windows utilities that don't allow / (they often use it as a command prefix), but that's not true for Windows the operating system. – James Moore Jan 09 '21 at 23:05
84

Current Working Directory

To get the current working directory, you can use:

process.cwd()

However, be aware that some scripts, notably gulp, will change the current working directory with process.chdir().

Node Module Path

You can get the path of the current module with:

  • __filename
  • __dirname

Original Directory (where the command was initiated)

If you are running a script from the command line, and you want the original directory from which the script was run, regardless of what directory the script is currently operating in, you can use:

process.env.INIT_CWD

Original directory, when working with NPM scripts

It's sometimes desirable to run an NPM script in the current directory, rather than the root of the project.

This variable is available inside npm package scripts as:

$INIT_CWD.

You must be running a recent version of NPM. If this variable is not available, make sure NPM is up to date.

This will allow you access the current path in your package.json, e.g.:

scripts: {
  "customScript": "gulp customScript --path $INIT_CWD"
}
i alarmed alien
  • 9,412
  • 3
  • 27
  • 40
superluminary
  • 47,086
  • 25
  • 151
  • 148
  • 1
    `process.env.INIT_CWD` returns the dir of `package.json` – vaughan May 30 '18 at 18:45
  • 2
    Watch out, $INIT_CWD only works on Linux. For Windows, you'll have to use %INIT_CWD%. I think this issue can be overcome by using https://www.npmjs.com/package/cross-env , but I haven't tried it myself – Stephanie Nov 29 '18 at 15:05
4

path.resolve('.') is also a reliable and clean option, because we almost always require('path'). It will give you absolute path of the directory from where it is called.

sziraqui
  • 5,763
  • 3
  • 28
  • 37
3

Alternatively, if you want to solely obtain the current directory of the current NodeJS script, you could try something simple like this. Note that this will not work in the Node CLI itself:

var fs = require('fs'),
    path = require('path');

var dirString = path.dirname(fs.realpathSync(__filename));

// output example: "/Users/jb/workspace/abtest"
console.log('directory to start walking...', dirString);
1

Warning if using ES Modules

According to the ECMAScript modules docs:

CommonJS variables __filename or __dirname are not available in ES modules.
Instead, use cases can be replicated via import.meta.url.

So according to why is __dirname not defined in node?, you can do the following:

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

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
KyleMit
  • 30,350
  • 66
  • 462
  • 664
0

Here's what worked for me:

console.log(process.mainModule.filename);
Etienne Martin
  • 10,018
  • 3
  • 35
  • 47