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.
On this page · 5 min · Beginner
On this page
- Learning objectives
- Explanation
- Syntax
- Code example
- Step by step
- Real-world use
- Common mistakes
- Best practices
- Remember this
- Practice exercise
- Mini quiz
- Related topics
- My notes
- Reading time
- 5 min
- Difficulty
- Beginner
- Updated
- Oct 28, 2026
Related tutorials
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#
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)#
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); }
/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/passwdThis example is illustrative. Copy or download it and run it in your own environment; the expected output is shown above.
Step-by-step explanation#
- join cleans the path: “2026/..” cancels out.
- basename, dirname and extname split the path; only the last dot counts as the extension.
- parse returns every part as an object.
- relative computes the route between two folders.
- 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#
"uploads/" + name breaks on Windows and allows traversal. Use path.join/resolve.
Relative paths depend on where node was started. Base paths on import.meta.dirname.
“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?
Show solution
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#
What does path.posix.extname("archive.tar.gz") return?
Want more? Practise all Node.js MCQs · Node.js interview questions
My notes#
Saved in this browser.