Pure path utilities for VFS.
All public ops on VFS and the VFS.Mountable protocol expect absolute,
already-normalized paths with a leading /. This module is the canonical
place for path manipulation; backends should not roll their own.
Paths are POSIX-shaped: /-separated, with . (current) and .. (parent)
segments collapsed by normalize/1. .. at the root is a no-op (root is
its own parent), matching POSIX semantics.
Summary
Functions
Returns true if path starts with /.
Last segment of a path. The basename of the root is the empty string.
Parent directory. The parent of / is / (POSIX semantics).
Join an absolute base with a relative or absolute path. The result is
normalized. If path is itself absolute, the base is ignored (matches
Path.join/2 behavior).
Normalize an absolute path: collapse . and .. segments and remove
consecutive slashes. The result has a leading / and no trailing slash
except for the root.
Re-root path under prefix, returning the remainder as an absolute path
under the new root. Returns :error when prefix is not a path-segment
prefix of path. Used for mount-prefix stripping.
Split a normalized path into its segments. The root splits to [].
Types
@type t() :: String.t()
An absolute, normalized path with a leading / and no trailing slash (except root).
Functions
Returns true if path starts with /.
Examples
iex> VFS.Path.absolute?("/foo")
true
iex> VFS.Path.absolute?("foo")
false
Last segment of a path. The basename of the root is the empty string.
Examples
iex> VFS.Path.basename("/foo/bar")
"bar"
iex> VFS.Path.basename("/")
""
Parent directory. The parent of / is / (POSIX semantics).
Examples
iex> VFS.Path.dirname("/foo/bar")
"/foo"
iex> VFS.Path.dirname("/foo")
"/"
iex> VFS.Path.dirname("/")
"/"
Join an absolute base with a relative or absolute path. The result is
normalized. If path is itself absolute, the base is ignored (matches
Path.join/2 behavior).
Examples
iex> VFS.Path.join("/foo", "bar")
"/foo/bar"
iex> VFS.Path.join("/foo/bar", "../baz")
"/foo/baz"
iex> VFS.Path.join("/foo", "/abs/ignored-base")
"/abs/ignored-base"
Normalize an absolute path: collapse . and .. segments and remove
consecutive slashes. The result has a leading / and no trailing slash
except for the root.
Raises ArgumentError on non-absolute input.
Examples
iex> VFS.Path.normalize("/foo/./bar/../baz")
"/foo/baz"
iex> VFS.Path.normalize("//foo//bar/")
"/foo/bar"
iex> VFS.Path.normalize("/")
"/"
iex> VFS.Path.normalize("/../foo")
"/foo"
Re-root path under prefix, returning the remainder as an absolute path
under the new root. Returns :error when prefix is not a path-segment
prefix of path. Used for mount-prefix stripping.
Examples
iex> VFS.Path.relative_to("/foo/bar/baz", "/foo")
{:ok, "/bar/baz"}
iex> VFS.Path.relative_to("/foo/bar", "/foo/bar")
{:ok, "/"}
iex> VFS.Path.relative_to("/foo/bar", "/")
{:ok, "/foo/bar"}
iex> VFS.Path.relative_to("/foobar", "/foo")
:error
Split a normalized path into its segments. The root splits to [].
Examples
iex> VFS.Path.split("/foo/bar/baz")
["foo", "bar", "baz"]
iex> VFS.Path.split("/")
[]