path.parse()

Splits a path string into an object with root, dir, base, name and ext properties.

Signature
path.parse(path)
  • Added in Node.js v0.11.15

Parameters

ParameterTypeDescription
$pathstringThe path to parse. Trailing directory separators are ignored.

Return value

ObjectAn object with string properties root, dir, base, ext and name describing the significant elements of the path.

Errors

Throws a TypeError (ERR_INVALID_ARG_TYPE) if path is not a string.

path.parse() returns every significant element of a path in one object, saving you three or four separate calls. The properties are:

  • root — the filesystem root, '/' on POSIX or 'C:\' on Windows; an empty string for a relative path.
  • dir — the same value path.dirname() would return.
  • base — the last component, extension included, as path.basename() gives it.
  • name — base with ext removed.
  • ext — the extension including its dot, as path.extname() gives it.

The invariant that matters is base === name + ext, and path.format() is the exact inverse: feed the object straight back and you get an equivalent path.

What trips people up

Trailing separators are ignored, so parsing '/srv/app/' reports base: 'app' — the final directory is treated as the base, exactly as basename() would. There is nothing in the result that tells you whether the path names a file or a directory; only the filesystem knows.

Dotfiles inherit extname()'s rule: '.gitignore' parses to name: '.gitignore' with an empty ext, not to name: ''.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Renaming a batch of files by changing only the name or only the extension
  • Reading directory, stem and suffix in one call instead of three
  • Grouping a file listing by extension while keeping the stem for display

Frequently asked questions

How do I split a file path into its parts in Node.js?

Call path.parse(p), which returns an object with root, dir, base, name and ext. It replaces separate calls to dirname(), basename() and extname(), and the returned object can be handed straight to path.format() to rebuild a path.

What is the difference between base and name in path.parse?

base is the full final component including the extension, while name is that component with the extension removed. For 'index.html', base is 'index.html' and name is 'index'. The relationship base === name + ext always holds.

Does path.parse tell me whether a path is a file or a directory?

No. It performs pure string parsing and never touches the filesystem, so a directory path like '/srv/app/' simply reports base 'app' with an empty ext. Use fs.statSync(p).isDirectory() when you need the real answer.

More examples

parse() and format() are inverses

format() rebuilds the original string exactly. The second half shows the one rule to remember: base takes priority over name and ext, so you must clear base before an edit to name or ext has any effect.

Example · javascript
const path = require('node:path');

const original = '/srv/app/public/index.html';
const parts = path.posix.parse(original);

console.log('round trip:', path.posix.format(parts));
console.log('identical: ', path.posix.format(parts) === original);

// change the extension: clear base so name + ext are used
parts.base = undefined;
parts.ext = '.htm';
console.log('retargeted:', path.posix.format(parts));

Batch-renaming with the parsed pieces

Destructuring dir and name off the parse result — and deliberately not carrying base along — lets format() build the new filename from the edited pieces. The listing confirms both files became '-v2.md'.

Example · javascript
const path = require('node:path');
const fs = require('node:fs');

fs.mkdirSync('parse-demo', { recursive: true });
for (const f of ['notes.txt', 'todo.txt']) {
  fs.writeFileSync(path.join('parse-demo', f), '');
}

for (const f of fs.readdirSync('parse-demo')) {
  const { dir, name } = path.parse(path.join('parse-demo', f));
  fs.renameSync(path.join('parse-demo', f), path.format({ dir, name: name + '-v2', ext: '.md' }));
}

console.log(fs.readdirSync('parse-demo').sort());

fs.rmSync('parse-demo', { recursive: true, force: true });
console.log('cleaned up:', fs.existsSync('parse-demo'));

Trailing separators and roots

The first result shows that a directory path is parsed just like a file path, with the final component landing in base. The root property is the only piece that differs structurally between platforms, which is why win32 reports 'C:\' where POSIX reports '/'.

Example · javascript
const path = require('node:path');

console.log(path.posix.parse('/srv/app/'));
// base is 'app': the trailing slash is ignored

console.log(path.posix.parse('/'));
// root '/', dir '/', base '' — nothing left to name

console.log(path.win32.parse('C:\\path\\dir\\file.txt').root);
// -> C:\   (drive letter is part of the root on Windows)

Discussion

  • Be the first to comment on this lesson.