Is there a built-in javascript function similar to os.path.join?
Use the path
module. path.join
is exactly what you're looking for. From the docs:
path.join([path1][, path2][, ...])#
Join all arguments together and normalize the resulting path.Arguments must be strings. In v0.8, non-string arguments were silently ignored. In v0.10 and up, an exception is thrown.
Example:
const path = require('node:path') path.join('/foo', 'bar', 'baz/asdf', 'quux', '..') // returns '/foo/bar/baz/asdf' path.join('foo', {}, 'bar') // throws exception TypeError: Arguments to path.join must be strings
You can also use import path from 'path'
instead of const path = require('node:path')
if you're loading modules with that style.
Edit:
I assumed here that you're using server-side Javascript like node.js. If you want to use it in the browser, you can use path-browserify.
The accepted answer doesn't work for URLs, it removes the double slash after the protocolhttps://hostname
becomes https:/hostname
.
Most other answers do not handle the first and last part differently. A slash at the beginning or end should not be removed, it would change the meaning (relative/absolute) (file/directory) of the joined path.
Below is a modified version of the accepted answer:
function pathJoin(parts, sep){
const separator = sep || '/';
parts = parts.map((part, index)=>{
if (index) {
part = part.replace(new RegExp('^' + separator), '');
}
if (index !== parts.length - 1) {
part = part.replace(new RegExp(separator + '$'), '');
}
return part;
})
return parts.join(separator);
}
usage:
console.log(pathJoin(['https://', 'hostname', 'path/'])); // 'https://hostname/path/'
console.log(pathJoin(['relative/', 'path', 'to/dir/'])); // 'relative/path/to/dir/'
console.log(pathJoin(['/absolute/', 'path', 'to/file'])); // '/absolute/path/to/file'
https://jsfiddle.net/tdsLencu/
Building on @Berty's reply, this ES6 variant preserves all leading slashes, to work with protocol relative url's (like //stackoverflow.com
), and also ignores any empty parts:
build_path = (...args) => {
return args.map((part, i) => {
if (i === 0) {
return part.trim().replace(/[\/]*$/g, '')
} else {
return part.trim().replace(/(^[\/]*|[\/]*$)/g, '')
}
}).filter(x=>x.length).join('/')
}
build_path("http://google.com/", "my", "path")
will return"http://google.com/my/path"
build_path("//a", "", "/", "/b/")
will return"//a/b"
build_path()
will return""
Note that this regex strips trailing slashes. Sometimes a trailing slash carries semantic meaning (e.g. denoting a directory rather than a file), and that distinction will be lost here.
There isn't currently a built-in that will perform a join while preventing duplicate separators. If you want concise, I'd just write your own:
function pathJoin(parts, sep){
var separator = sep || '/';
var replace = new RegExp(separator+'{1,}', 'g');
return parts.join(separator).replace(replace, separator);
}
var path = pathJoin(['a/', 'b', 'c//'])