Node.js Path Module

The path module provides cross-platform utilities for building, parsing, and normalizing file system paths without hand-rolling string concatenation.

Why Use the path Module

It's tempting to build a file path by gluing strings together with a forward slash, but that approach breaks the moment your code runs on Windows, where paths use backslashes, or when a folder name accidentally contains a trailing slash. Node's core path module, brought in with require('node:path'), abstracts away those operating-system differences so the same code produces a correct path on Linux, macOS, and Windows alike.

Joining and Resolving Paths

path.join() takes any number of path segments, concatenates them with the correct separator for the current OS, and normalizes the result (collapsing things like './' and resolving '..'). path.resolve() does something subtly different: it processes segments from right to left, building an absolute path, and stops as soon as it has constructed one—falling back to the current working directory if none of the segments were already absolute. In practice, join() is what you reach for to combine known pieces, while resolve() is what you reach for when you need a guaranteed absolute path.

  • path.join(...segments) — combines segments into one normalized path
  • path.resolve(...segments) — builds an absolute path, resolving against the current working directory if needed
  • path.basename(path) — returns the last portion of a path (the file or folder name)
  • path.extname(path) — returns the file extension, including the leading dot
  • path.dirname(path) — returns everything before the last segment
  • path.parse(path) — returns an object with root, dir, base, ext, and name all at once

join() vs resolve()

const path = require('node:path');

const joined = path.join('users', 'alice', '..', 'bob', 'notes.txt');
console.log(joined); // users/bob/notes.txt (segments combined and normalized)

const resolved = path.resolve('users', 'bob', 'notes.txt');
console.log(resolved); // e.g. /home/project/users/bob/notes.txt (absolute path)

const resolvedFromRoot = path.resolve('/etc', 'config', 'app.json');
console.log(resolvedFromRoot); // /etc/config/app.json — stops once absolute

Extracting Path Components

Once you have a path, you often need to pull out just one piece of it: the directory it lives in, its file name, or its extension. path.dirname, path.basename, and path.extname each isolate one component, while path.parse hands back all of them at once as a plain object—useful when you need several pieces and don't want to call multiple functions.

Extracting components from a path

const path = require('node:path');

const filePath = '/projects/app/src/index.js';

console.log(path.dirname(filePath));  // /projects/app/src
console.log(path.basename(filePath)); // index.js
console.log(path.extname(filePath));  // .js

// Strip the extension by passing it as the second argument to basename
console.log(path.basename(filePath, path.extname(filePath))); // index

console.log(path.parse(filePath));
// { root: '/', dir: '/projects/app/src', base: 'index.js', ext: '.js', name: 'index' }
MethodDescriptionExample InputExample Output
path.join()Concatenates and normalizes segmentsjoin('a', 'b', 'c.txt')a/b/c.txt
path.resolve()Builds an absolute pathresolve('data', 'c.txt')/current/working/dir/data/c.txt
path.basename()Last portion of the pathbasename('/a/b/c.txt')c.txt
path.extname()File extension with leading dotextname('/a/b/c.txt').txt
path.dirname()Everything before the last segmentdirname('/a/b/c.txt')/a/b

Building an absolute path relative to the current file

const path = require('node:path');

// __dirname is the directory of the currently executing file
const dataFilePath = path.join(__dirname, 'data', 'users.json');
console.log(dataFilePath);
// e.g. /home/project/scripts/data/users.json — correct on every OS
Note: path.sep gives you the OS-specific separator ('/' on POSIX, '\\' on Windows) if you ever need it directly, but in almost all cases join() and resolve() make manual separator handling unnecessary.

Exercise: Node.js Path Module

What is the main purpose of Node.js's path module?