path
import path
Pure string manipulation over /-separated paths. Nothing here touches the
filesystem; use fs for that. The separator is / on every
platform — Windows-style \ paths are not interpreted.
Splitting a path apart
Section titled “Splitting a path apart”| Function | Signature |
|---|---|
path.dirname(p) | String -> String |
path.basename(p) | String -> String |
path.extension(p) | String -> Option[String] |
path.stem(p) | String -> String |
import path
fn main() -> Unit = { println(path.dirname("/var/log/app.log")) // /var/log println(path.basename("/var/log/app.log")) // app.log println(path.stem("/var/log/app.log")) // app println(path.extension("app.log") ?? "-") // log}extension returns the last extension with no leading dot, and none when
there is none. Two edge cases are worth knowing:
dirname("app.log")is"", not".".- A dotfile is asymmetric:
extension(".hidden")issome("hidden")whilestem(".hidden")is".hidden". Do not assumestem + "." + extensionreconstructs the input.
Building and cleaning
Section titled “Building and cleaning”| Function | Signature |
|---|---|
path.join(base, child) | (String, String) -> String |
path.normalize(p) | String -> String |
path.is_absolute(p) | String -> Bool |
path.join("var", "log") // var/logpath.join("var/", "log") // var/log — one trailing slash is absorbedpath.join("/usr/lib", "/etc") // /etc — an absolute child replaces basepath.normalize("/a/./b/../c") // /a/cpath.normalize("a/../../c") // ../c — relative paths keep leading ..path.normalize("/../a") // /a — absolute paths cannot escape rootjoin with an empty child keeps the trailing slash (join("a", "") is "a/").
SafePath
Section titled “SafePath”SafePath is an opaque type for paths that have been checked for traversal.
Construct it through from_string, which rejects anything containing a ..
segment:
| Function | Signature |
|---|---|
path.from_string(s) | String -> Result[SafePath, String] |
path.trusted(s) | String -> SafePath |
path.to_string(p) | SafePath -> String |
match path.from_string(user_input) { ok(p) => read_it(path.to_string(p)), err(e) => println(e), // path traversal rejected: ../../etc/passwd}trusted is the deliberate escape hatch for paths you constructed yourself. It
performs no checking — the name is the documentation.