Back to Blog
Node.jsPathFilesBackend

Node.js Path Module Guide

Master the Node.js path module for cross-platform file path manipulation.

B
Bootspring Team
Engineering
October 31, 2018
5 min read

The path module provides utilities for working with file and directory paths. Here's how to use it effectively.

Import#

1import path from 'node:path'; 2 3// Or specific methods 4import { join, resolve, basename } from 'node:path'; 5 6// Platform-specific 7import { posix, win32 } from 'node:path';

path.join()#

1// Join path segments 2const fullPath = path.join('users', 'john', 'documents'); 3// 'users/john/documents' (Unix) 4// 'users\\john\\documents' (Windows) 5 6// Handles extra slashes 7path.join('/foo/', '/bar/', 'baz/'); 8// '/foo/bar/baz' 9 10// Resolves . and .. 11path.join('foo', 'bar', '..', 'baz'); 12// 'foo/baz' 13 14// Practical usage 15const configPath = path.join(process.cwd(), 'config', 'app.json'); 16const dataPath = path.join(__dirname, '..', 'data', 'users.json');

path.resolve()#

1// Resolve to absolute path 2const absolute = path.resolve('foo', 'bar'); 3// '/current/working/directory/foo/bar' 4 5// With leading slash - starts from root 6path.resolve('/foo', 'bar'); 7// '/foo/bar' 8 9// Rightmost absolute path wins 10path.resolve('foo', '/bar', 'baz'); 11// '/bar/baz' 12 13// Common patterns 14const projectRoot = path.resolve(__dirname, '..'); 15const configFile = path.resolve(projectRoot, 'config.json'); 16 17// From current directory 18const uploadDir = path.resolve('./uploads');

path.basename()#

1// Get filename from path 2path.basename('/foo/bar/file.txt'); 3// 'file.txt' 4 5// Remove extension 6path.basename('/foo/bar/file.txt', '.txt'); 7// 'file' 8 9// Works with any path 10path.basename('C:\\Users\\file.txt'); 11// 'file.txt' (on Unix, would be 'C:\\Users\\file.txt') 12 13// Get just the filename 14const files = ['/path/to/a.js', '/path/to/b.js']; 15const names = files.map(f => path.basename(f, '.js')); 16// ['a', 'b']

path.dirname()#

1// Get directory from path 2path.dirname('/foo/bar/file.txt'); 3// '/foo/bar' 4 5path.dirname('/foo/bar/'); 6// '/foo' 7 8path.dirname('file.txt'); 9// '.' 10 11// Navigate up directories 12const parentDir = path.dirname(__dirname); 13const grandparent = path.dirname(path.dirname(__dirname));

path.extname()#

1// Get file extension 2path.extname('file.txt'); 3// '.txt' 4 5path.extname('file.config.js'); 6// '.js' 7 8path.extname('file'); 9// '' 10 11path.extname('.gitignore'); 12// '' 13 14path.extname('file.'); 15// '.' 16 17// Filter by extension 18const files = ['app.js', 'style.css', 'data.json', 'readme.md']; 19const jsFiles = files.filter(f => path.extname(f) === '.js'); 20// ['app.js']

path.parse()#

1// Parse path into components 2const parsed = path.parse('/home/user/file.txt'); 3// { 4// root: '/', 5// dir: '/home/user', 6// base: 'file.txt', 7// ext: '.txt', 8// name: 'file' 9// } 10 11// Windows path 12path.win32.parse('C:\\Users\\file.txt'); 13// { 14// root: 'C:\\', 15// dir: 'C:\\Users', 16// base: 'file.txt', 17// ext: '.txt', 18// name: 'file' 19// } 20 21// Use parsed components 22const { name, ext } = path.parse(filename); 23const newName = `${name}.backup${ext}`;

path.format()#

1// Build path from components 2const pathString = path.format({ 3 dir: '/home/user', 4 base: 'file.txt' 5}); 6// '/home/user/file.txt' 7 8// With all components 9path.format({ 10 root: '/', 11 dir: '/home/user', 12 name: 'file', 13 ext: '.txt' 14}); 15// '/home/user/file.txt' 16 17// base overrides name + ext 18path.format({ 19 name: 'ignored', 20 ext: '.ignored', 21 base: 'file.txt' 22}); 23// 'file.txt' 24 25// Rename file 26function renameFile(filepath, newName) { 27 const parsed = path.parse(filepath); 28 return path.format({ 29 dir: parsed.dir, 30 name: newName, 31 ext: parsed.ext 32 }); 33} 34 35renameFile('/foo/old.txt', 'new'); 36// '/foo/new.txt'

path.relative()#

1// Get relative path between two paths 2path.relative('/data/files', '/data/files/test/file.txt'); 3// 'test/file.txt' 4 5path.relative('/data/files', '/data/other/file.txt'); 6// '../other/file.txt' 7 8path.relative('/a/b/c', '/a/b/c'); 9// '' 10 11// Practical: create relative imports 12function getRelativeImport(from, to) { 13 let relative = path.relative(path.dirname(from), to); 14 if (!relative.startsWith('.')) { 15 relative = './' + relative; 16 } 17 return relative.replace(/\\/g, '/'); 18} 19 20getRelativeImport('/src/components/Button.js', '/src/utils/helpers.js'); 21// '../utils/helpers.js'

path.isAbsolute()#

1// Check if path is absolute 2path.isAbsolute('/foo/bar'); // true 3path.isAbsolute('./foo/bar'); // false 4path.isAbsolute('foo/bar'); // false 5 6// Windows 7path.win32.isAbsolute('C:\\foo'); // true 8path.win32.isAbsolute('\\foo'); // true 9path.win32.isAbsolute('foo'); // false 10 11// Validate input 12function processFile(filepath) { 13 const absolutePath = path.isAbsolute(filepath) 14 ? filepath 15 : path.resolve(process.cwd(), filepath); 16 17 // Now work with absolute path 18 return absolutePath; 19}

path.normalize()#

1// Normalize path (resolve . and ..) 2path.normalize('/foo/bar//baz/asdf/quux/..'); 3// '/foo/bar/baz/asdf' 4 5path.normalize('C:\\temp\\\\foo\\bar\\..\\'); 6// 'C:\\temp\\foo\\' 7 8// Clean up user input 9function cleanPath(inputPath) { 10 return path.normalize(inputPath); 11} 12 13// Note: doesn't check if path exists 14path.normalize('/nonexistent/../foo'); 15// '/foo'

path.sep and path.delimiter#

1// Path separator 2path.sep; 3// '/' on Unix, '\\' on Windows 4 5// Split path into segments 6'/foo/bar/baz'.split(path.sep); 7// ['', 'foo', 'bar', 'baz'] 8 9// PATH delimiter 10path.delimiter; 11// ':' on Unix, ';' on Windows 12 13// Parse PATH environment variable 14const paths = process.env.PATH.split(path.delimiter); 15 16// Build PATH 17const newPath = ['/usr/local/bin', '/usr/bin'].join(path.delimiter);

Cross-Platform Paths#

1// Always use path.join for cross-platform 2// BAD 3const bad = dir + '/' + file; 4 5// GOOD 6const good = path.join(dir, file); 7 8// Force specific platform 9path.posix.join('foo', 'bar'); // Always 'foo/bar' 10path.win32.join('foo', 'bar'); // Always 'foo\\bar' 11 12// Convert Windows path to URL 13function pathToFileUrl(filepath) { 14 const absolute = path.resolve(filepath); 15 return 'file://' + absolute.split(path.sep).join('/'); 16} 17 18// Normalize slashes for URLs 19function normalizeForUrl(filepath) { 20 return filepath.replace(/\\/g, '/'); 21}

Common Patterns#

1// Get project root (ES modules) 2import { fileURLToPath } from 'node:url'; 3 4const __filename = fileURLToPath(import.meta.url); 5const __dirname = path.dirname(__filename); 6const projectRoot = path.resolve(__dirname, '..'); 7 8// Ensure extension 9function ensureExtension(filepath, ext) { 10 if (path.extname(filepath) !== ext) { 11 return filepath + ext; 12 } 13 return filepath; 14} 15 16// Change extension 17function changeExtension(filepath, newExt) { 18 const { dir, name } = path.parse(filepath); 19 return path.join(dir, name + newExt); 20} 21 22changeExtension('/foo/bar.txt', '.md'); 23// '/foo/bar.md' 24 25// Safe path joining (prevent traversal) 26function safePath(baseDir, userPath) { 27 const resolved = path.resolve(baseDir, userPath); 28 if (!resolved.startsWith(baseDir)) { 29 throw new Error('Path traversal detected'); 30 } 31 return resolved; 32}

Best Practices#

Cross-Platform: ✓ Always use path.join() ✓ Use path.sep when needed ✓ Test on multiple OS ✓ Avoid hardcoded separators Security: ✓ Validate user-provided paths ✓ Prevent path traversal ✓ Use path.resolve for absolute ✓ Sanitize file names ES Modules: ✓ Use import.meta.url ✓ Convert to __dirname ✓ Use fileURLToPath ✓ Handle Windows paths Avoid: ✗ String concatenation for paths ✗ Hardcoded '/' or '\\' ✗ Trusting user input ✗ Mixing path styles

Conclusion#

The path module is essential for cross-platform file path handling. Use path.join() for combining paths, path.resolve() for absolute paths, and path.parse()/path.format() for manipulation. Always use path module methods instead of string concatenation to ensure cross-platform compatibility.

Share this article

Help spread the word about Bootspring