path.basename()

Returns the last portion of a path, optionally with a trailing suffix removed.

Signature
path.basename(path[, suffix])
  • Added in Node.js v0.1.25

Parameters

ParameterTypeDescription
$pathstringThe path to take the last portion of.
$suffixoptionalstringAn optional suffix to remove from the end of the result.

Return value

stringThe last portion of the path, with any trailing directory separators ignored and the suffix removed if it matches.

Errors

Throws a TypeError if path is not a string, or if suffix is given and is not a string.

Changelog

  • PHP v6.0.0Passing a non-string as the path argument now throws instead of coercing.

path.basename() returns the final component of a path, mirroring the Unix basename command. Trailing separators are ignored, so '/srv/app/reports/' yields 'reports' — the function does not care whether the component names a file or a directory.

The optional second argument removes a suffix from the end of the result, which is the idiomatic way to get a filename without its extension. It is a literal suffix match, not an extension parser, so you can strip any trailing string you like.

What trips people up

The suffix match is case-sensitive on every platform, including Windows. path.basename('README.MD', '.md') returns 'README.MD' unchanged. Lowercase the extension yourself, or pair the call with path.extname(), which reads the actual extension off the string.

The suffix is also only removed when the result would not become empty: path.basename('.md', '.md') returns '.md', not an empty string.

For multi-dot names, only the last extension is an extension. path.basename('archive.tar.gz', '.gz') gives 'archive.tar'. If you want every part of the name, path.parse() hands back name and ext in one call.

Example

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

When to use it

  • Displaying just the filename in a log line or CLI progress output
  • Deriving an output name by stripping the input extension before adding a new one
  • Reading the current directory's name out of process.cwd()

Frequently asked questions

How do I get a filename without its extension in Node.js?

Pass the extension as the second argument: path.basename('report.pdf', '.pdf') returns 'report'. When the extension is not known ahead of time, combine the two calls as path.basename(file, path.extname(file)), or read the name property from path.parse(file).

Why did path.basename not strip my suffix?

Almost always because the case did not match — the comparison is case-sensitive on every platform, so '.PNG' does not match '.png'. It also refuses to strip a suffix that would leave an empty result, which is why path.basename('.md', '.md') returns '.md'.

Does path.basename work on directory paths?

Yes. It ignores trailing separators and returns the last component regardless of whether it names a file or a directory, so both '/srv/app/reports' and '/srv/app/reports/' return 'reports'. A root path such as '/' returns an empty string.

More examples

Stripping whatever extension a file actually has

Feeding path.extname() into the suffix argument sidesteps the case-sensitivity trap, because extname() returns the extension exactly as it appears in the string. Note that 'archive.tar.gz' loses only '.gz' — extname() considers just the final dot.

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

for (const file of ['report.pdf', 'archive.tar.gz', 'Makefile', 'LOGO.PNG']) {
  const stem = path.basename(file, path.extname(file));
  console.log(file.padEnd(16), '->', stem);
}

Renaming files by replacing their extension

basename() supplies the stem, dirname() supplies the folder, and join() puts the new name back together. The readdir output confirms the file on disk is now notes.md.

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

fs.mkdirSync('basename-demo', { recursive: true });
fs.writeFileSync(path.join('basename-demo', 'notes.txt'), 'hello\n');

const src = path.join('basename-demo', 'notes.txt');
const stem = path.basename(src, '.txt');
const dest = path.join(path.dirname(src), stem + '.md');

fs.renameSync(src, dest);
console.log('renamed to:', dest);
console.log('directory now:', fs.readdirSync('basename-demo'));

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

Windows paths are only understood on Windows

The POSIX implementation sees no '/' in a backslash path and therefore treats the entire string as one component. When you must parse paths from the other platform, use the explicit path.win32 or path.posix namespace rather than the default export.

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

console.log(path.win32.basename('C:\\foo\\bar.txt'));
// -> bar.txt

console.log(path.posix.basename('C:\\foo\\bar.txt'));
// -> C:\foo\bar.txt   (no POSIX separator, so the whole string is the basename)

console.log(path.win32.basename('C:\\foo.HTML', '.html'));
// -> foo.HTML   (suffix match is case-sensitive)

Discussion

  • Be the first to comment on this lesson.