path.basename()
Returns the last portion of a path, optionally with a trailing suffix removed.
path.basename(path[, suffix])- Added in Node.js v0.1.25
Parameters
| Parameter | Type | Description |
|---|---|---|
$path | string | The path to take the last portion of. |
$suffixoptional | string | An 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
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.
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.
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.
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