Created
November 12, 2013 18:10
-
-
Save creationix/7435851 to your computer and use it in GitHub Desktop.
Simple path join and dirname functions for generic javascript
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Joins path segments. Preserves initial "/" and resolves ".." and "." | |
// Does not support using ".." to go above/outside the root. | |
// This means that join("foo", "../../bar") will not resolve to "../bar" | |
function join(/* path segments */) { | |
// Split the inputs into a list of path commands. | |
var parts = []; | |
for (var i = 0, l = arguments.length; i < l; i++) { | |
parts = parts.concat(arguments[i].split("/")); | |
} | |
// Interpret the path commands to get the new resolved path. | |
var newParts = []; | |
for (i = 0, l = parts.length; i < l; i++) { | |
var part = parts[i]; | |
// Remove leading and trailing slashes | |
// Also remove "." segments | |
if (!part || part === ".") continue; | |
// Interpret ".." to pop the last segment | |
if (part === "..") newParts.pop(); | |
// Push new path segments. | |
else newParts.push(part); | |
} | |
// Preserve the initial slash if there was one. | |
if (parts[0] === "") newParts.unshift(""); | |
// Turn back into a single string path. | |
return newParts.join("/") || (newParts.length ? "/" : "."); | |
} | |
// A simple function to get the dirname of a path | |
// Trailing slashes are ignored. Leading slash is preserved. | |
function dirname(path) { | |
return join(path, ".."); | |
} |
Some issues I experienced when trying out this approach :
- Trailing
/
isn't preserved - Double
//
are replaced with/
when the first path is an absolute path that starts with the protocol (eg.blob://
,file://
,http://
,https://
, ...) - If your first path starts with
../
, it is stripped away
For me, that makes this approach pretty much unusable.
MSDOS cmd.exe and powershell accept '/' as well as '\'. It's only obscenely obsolete systems that reject '/' as a file separator. You might have a real reason for using a 386 system running MSDOS 3.1, but it probably doesn't involve running javascript :-)
Do you have a license, or at least allow other people to use this? It's beautiful, great and simple. Maybe you also want to check for escaped slashes (\/
on Unix), although URL encoding usually takes care of that well. :)
My variant:
/**
* A simple analog of Node.js's `path.join(...)`.
* https://gist.github.com/creationix/7435851#gistcomment-3698888
* @param {...string} segments
* @return {string}
*/
export default function joinPath(...segments) {
const parts = segments.reduce((parts, segment) => {
// Remove leading slashes from non-first part.
if (parts.length > 0) {
segment = segment.replace(/^\//, '')
}
// Remove trailing slashes.
segment = segment.replace(/\/$/, '')
return parts.concat(segment.split('/'))
}, [])
const resultParts = []
for (const part of parts) {
if (part === '.') {
continue
}
if (part === '..') {
resultParts.pop()
continue
}
resultParts.push(part)
}
return resultParts.join('/')
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Is there a license you could mention with this? Public domain doesn't exist everywhere as a concept and unattributed works can't be utilized without serious stares from legal and threats of the attack sharks. MIT, and I'd love you forever?