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 protocol
https://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//'])