Node.js · Modules

Path Module

Windows uses backslashes, Linux and macOS use forward slashes. The path module builds and takes apart file paths correctly on every system, so your code works everywhere.

Beginner 5 min Lesson 8 of 37Examples target Node.js 22 LTS.
Before you start:Modules
0/37 in Node.js
On this page · 5 min · Beginner

Learning objectives#

  • Build paths with path.join and path.resolve
  • Extract file names, folders and extensions
  • Compute relative paths
  • Keep user-supplied paths inside a safe folder

Explanation#

path.join("uploads", "2026", "a.png") joins segments with the right separator and cleans up . and .. parts.

path.resolve(...) builds an absolute path, starting from the current working directory unless a segment is already absolute. Combine with import.meta.dirname to be independent of where node was started.

path.basename (file name), path.dirname (folder), path.extname (".png") and path.parse (all parts at once) take paths apart.

path.relative(from, to) shows how to get from one folder to another.

Security: resolve user input against a base folder and check the result still starts with that base. This blocks ../../ path traversal.

path.sep is the separator of the current OS; path.posix and path.win32 force one style.

Syntax#

JavaScript Illustrative
import path from 'node:path';
path.join('a', 'b', 'c.txt');           // a/b/c.txt (a\b\c.txt on Windows)
path.resolve(import.meta.dirname, 'data');
path.extname('photo.jpeg');            // .jpeg

Code example: Working with paths safely (POSIX style for a stable output)#

JavaScriptpaths.js Illustrative
import path from 'node:path';


const p = path.posix;                  // forward slashes on every OS for this demo


const file = p.join('/srv/shop', 'uploads', '2026', '..', '2025', 'invoice.final.pdf');
console.log(file);
console.log('basename:', p.basename(file));
console.log('without ext:', p.basename(file, p.extname(file)));
console.log('dirname:', p.dirname(file));
console.log('extname:', p.extname(file));
console.log(p.parse(file));
console.log('relative:', p.relative('/srv/shop/uploads', '/srv/shop/logs/app.log'));


// Keep user input inside the uploads folder
const uploads = '/srv/shop/uploads';
function safePath(userFileName) {
  const target = p.resolve(uploads, userFileName);
  if (!target.startsWith(uploads + p.sep)) throw new Error(`Blocked: ${userFileName}`);
  return target;
}
console.log(safePath('photo.png'));
try { safePath('../../etc/passwd'); } catch (e) { console.log(e.message); }
Expected output
/srv/shop/uploads/2025/invoice.final.pdf
basename: invoice.final.pdf
without ext: invoice.final
dirname: /srv/shop/uploads/2025
extname: .pdf
{
  root: '/',
  dir: '/srv/shop/uploads/2025',
  base: 'invoice.final.pdf',
  ext: '.pdf',
  name: 'invoice.final'
}
relative: ../logs/app.log
/srv/shop/uploads/photo.png
Blocked: ../../etc/passwd

This example is illustrative. Copy or download it and run it in your own environment; the expected output is shown above.

Step-by-step explanation#

  1. join cleans the path: “2026/..” cancels out.
  2. basename, dirname and extname split the path; only the last dot counts as the extension.
  3. parse returns every part as an object.
  4. relative computes the route between two folders.
  5. safePath resolves the user input and rejects anything outside uploads.

Real-world use case#

A document service stores files at path.join(STORAGE_ROOT, tenantId, year, fileName) and uses the same safePath check before every read, so one customer can never reach another customer’s files.

Common mistakes#

String concatenation

"uploads/" + name breaks on Windows and allows traversal. Use path.join/resolve.

Relying on the current working directory

Relative paths depend on where node was started. Base paths on import.meta.dirname.

Trusting extname for security

“virus.exe.png” has extname .png. Validate file contents and types separately.

Best practices#

  • Always use path for paths
  • Anchor paths to import.meta.dirname
  • Resolve and check user-supplied paths
  • Use path.posix for URLs and cross-platform output

Remember this#

join = combine; resolve = absolute.

basename / dirname / extname / parse.

User path → resolve → must start with the base folder.

Practice exercise#

Your task: Write a function changeExt(file, newExt) that turns "report.draft.docx" into "report.draft.pdf" using the path module.

Need a hint?
Use path.parse, then path.format({ dir, name, ext }).
Show solution
JavaScript Illustrative
import path from 'node:path';


function changeExt(file, newExt) {
  const { dir, name } = path.parse(file);
  return path.format({ dir, name, ext: newExt });
}


console.log(changeExt('report.draft.docx', '.pdf'));   // report.draft.pdf

Mini quiz#

Path Module quizPredict the output Question 1 of 3

What does path.posix.extname("archive.tar.gz") return?

Score so far: 0/0

Want more? Practise all Node.js MCQs · Node.js interview questions

My notes#

Saved in this browser.

Progress is saved in this browser. Sign in to sync.