How to Get the Current Script Path in Node.js: Absolute Path Methods for All Contexts
Use __filename for CommonJS modules and fileURLToPath(import.meta.url) for ES modules to reliably retrieve the absolute path of the current script in any Node.js execution context.
When working with file system operations in the nodejs/node repository, determining the absolute path of the currently executing script requires different approaches depending on whether you use CommonJS or ES modules. The Node.js runtime exposes module location data through distinct global variables that vary by module system and execution context, such as worker threads or REPL environments.
CommonJS Modules: Using __filename
In CommonJS modules (the default require system), Node.js automatically defines the __filename variable as the absolute path of the current module before execution begins. This variable remains accurate even when the module is required by another file, providing a stable reference point for resolving relative paths.
According to the Node.js source code in lib/internal/worker.js at line 63, the runtime internally utilizes __filename when initializing worker threads, confirming its reliability across different execution scenarios.
// example.cjs
const path = require('node:path');
console.log('Absolute path:', path.resolve(__filename));
ES Modules: Converting import.meta.url
For ES modules (.mjs files or "type": "module" in package.json), __filename is not defined. Instead, you must use import.meta.url, which returns a file:// URL string. Convert this to a native filesystem path using fileURLToPath from the node:url module, as implemented in lib/url.js.
The Node.js codebase demonstrates this pattern in tools/dep_updaters/update-root-certs.mjs at line 11, where the script converts its own module URL to a path for loading adjacent certificate files.
// example.mjs
import { fileURLToPath } from 'node:url';
import path from 'node:path';
const __filename = fileURLToPath(import.meta.url);
console.log('Absolute path:', path.resolve(__filename));
Worker Threads and Entry Points
Worker threads inherit the module system of their parent context. For CommonJS workers, use __filename exactly as you would in the main thread. For ES module workers, use fileURLToPath(import.meta.url). The test suite in test/parallel/test-worker.js at line 9 illustrates this pattern for CommonJS contexts.
If you specifically need the entry script path (the file initially executed via node script.js), process.argv[1] serves as a fallback. However, this contains the path exactly as provided by the user (which may be relative) rather than a guaranteed absolute path, and it always points to the entry point rather than the current module.
REPL and Eval Contexts
When running code in the REPL or via node -e "code", neither __filename nor import.meta.url are defined because there is no associated file on disk. In these contexts, you must explicitly provide the file path through environment variables or command-line arguments.
Universal Helper for Mixed Codebases
For projects containing both CommonJS and ES modules, create a utility function that abstracts the module detection logic:
// utils/getCurrentFilePath.js
import { fileURLToPath } from 'node:url';
import path from 'node:path';
/**
* Returns the absolute path of the file that calls this function.
* Works for both CommonJS and ES modules.
*
* @returns {string} Absolute file path.
*/
export function getCurrentFilePath(importMeta) {
// ES module: convert the file URL to a path.
if (importMeta?.url) {
return fileURLToPath(importMeta.url);
}
// CommonJS: __filename is always available.
// eslint-disable-next-line no-undef
return __filename;
}
Usage in CommonJS:
const { getCurrentFilePath } = require('./utils/getCurrentFilePath');
console.log(getCurrentFilePath());
Usage in ES modules:
import { getCurrentFilePath } from './utils/getCurrentFilePath.js';
console.log(getCurrentFilePath(import.meta));
This helper checks for the presence of importMeta.url to detect ES module context, falling back to the global __filename for CommonJS environments.
Summary
- CommonJS: Use
path.resolve(__filename), which is automatically set by the runtime before module execution as seen inlib/internal/worker.js. - ES Modules: Use
fileURLToPath(import.meta.url)to convert the module URL to an absolute filesystem path, following the pattern intools/dep_updaters/update-root-certs.mjs. - Worker Threads: Apply the same method as the parent module system (
__filenamefor CJS,import.meta.urlfor ESM). - REPL/Eval: No built-in path variable exists; provide paths explicitly via environment variables.
- Cross-Platform: Both methods handle Windows and POSIX path separators correctly when combined with the
node:pathmodule.
Frequently Asked Questions
How do I get the current file path in a Node.js ES module?
Use fileURLToPath(import.meta.url) from the node:url module. This converts the file:// URL provided by import.meta.url into an absolute filesystem path that works consistently across Windows and POSIX systems.
What is the difference between __filename and import.meta.url?
__filename is a string containing the absolute filesystem path available only in CommonJS modules, while import.meta.url is a URL string (file://...) available only in ES modules. ES modules require the fileURLToPath() function to convert the URL to a usable filesystem path.
Can I use process.argv[1] to get the current script path?
process.argv[1] returns the entry script path as provided to the Node.js command, but it may be relative (e.g., ./script.js rather than /home/user/project/script.js). It also points to the initial entry point, not the current module if your code is imported elsewhere, making it unreliable for module-specific path resolution.
Why is __dirname undefined in my ES module?
__dirname is a CommonJS-specific variable that is not defined in ES modules. To recreate it, compute the directory from the file path: const __dirname = path.dirname(fileURLToPath(import.meta.url)).
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →