Pure-string pathname manipulation on the Path class.
PathPure-string pathname manipulation: join, dirname, basename, ext, split, absolute?.
No filesystem access – every method is a total string function; pair with the File class for stat/exists?.
(Path join . parts)Join components with exactly one ‘/’ at each seam (a component’s own leading/trailing slashes collapse into the seam). Empty components vanish.
Parameters:
STRING — Path componentsReturns: STRING — The joined path
Examples:
(Path join "a" "b/c") => "a/b/c"
(Path join "a/" "/b") => "a/b"
(Path join "/root" "etc") => "/root/etc"
(Path join "a" "" "b") => "a/b"(Path dirname p)The directory part: everything before the last ‘/’ (after trailing slashes are stripped). No slash at all answers “.”; a root-level entry answers “/”.
Parameters:
STRING — PathReturns: STRING — The directory part
Examples:
(Path dirname "/a/b/c.txt") => "/a/b"
(Path dirname "c.txt") => "."
(Path dirname "/etc") => "/"(Path basename p)The final component: everything after the last ‘/’ (after trailing slashes are stripped).
Parameters:
STRING — PathReturns: STRING — The final path component
Examples:
(Path basename "/a/b/c.txt") => "c.txt"
(Path basename "c.txt") => "c.txt"
(Path basename "/a/b/") => "b"(Path ext p)The extension of the basename, without its dot – or nil when there is none (a leading-dot name like “.bashrc” has no extension; absence is nil, never a sentinel).
Parameters:
STRING — PathReturns: ANY — Extension string, or nil
Examples:
(Path ext "a/b.tar.gz") => "gz"
(null? (Path ext "Makefile")) => #t
(null? (Path ext ".bashrc")) => #t(Path split p)The path’s components as a list of strings; empty components (doubled or leading/trailing slashes) are dropped. Pair with absolute? to keep the root bit.
Parameters:
STRING — PathReturns: LIST — Component strings
Examples:
(Path split "/a/b/c") => ("a" "b" "c")
(Path split "a//b/") => ("a" "b")(Path norm p)Lexically normalize: ‘.’ and empty components drop, ‘..’ consumes the component before it. Leading ‘..’s survive (nothing to consume – the CALLER decides whether climbing out is an error), and an absolute path never climbs above ‘/’. Purely lexical: no symlink is consulted.
Parameters:
STRING — PathReturns: STRING — The normalized path
Examples:
(Path norm "a/./b//c") => "a/b/c"
(Path norm "a/b/../c") => "a/c"
(Path norm "../a") => "../a"
(Path norm "a/..") => "."
(Path norm "/a/../..") => "/"(Path strip-ext p)p without the basename’s extension and its dot; unchanged when ext is nil. The whole path keeps its directory part – this is the typed door for the byte-arithmetic suffix strips the tools hand-rolled.
Parameters:
STRING — PathReturns: STRING — The path minus its extension
Examples:
(Path strip-ext "a/b.x") => "a/b"
(Path strip-ext "a.tar.gz") => "a.tar"
(Path strip-ext "Makefile") => "Makefile"(Path absolute? p)Does p start at the root?
Parameters:
STRING — PathReturns: BOOL — True when p begins with ‘/’
Examples:
(Path absolute? "/etc") => #t
(Path absolute? "etc") => #f(Path relpath start p)Express p relative to start, lexically (#364): both are normalized, the common prefix drops, and each remaining start segment becomes ‘..’. Both must be absolute or both relative – mixing raises tag ‘value (relating them needs a working directory, which this pure-string class refuses to consult); a relative start that still climbs (‘..’ after norm) raises for the same reason.
Parameters:
STRING — The path to be relative FROMSTRING — The path to express relative to startReturns: STRING — p relative to start (‘.’ when they coincide)
Examples:
(Path relpath "/a/b" "/a/c/d") => "../c/d"
(Path relpath "a/b" "a/b") => "."
(Path relpath "/a" "/a/b") => "b"(Path match? pattern p)Glob-match p against pattern, segment-aware (#364): ‘?’ matches one non-‘/’ character, ‘*’ a non-‘/’ run, and ‘**’ AS A FULL SEGMENT matches zero or more whole segments. No character classes (the […] form) – purely lexical, no filesystem access.
Parameters:
STRING — Glob pattern: ? one char, * a run, ** a whole-segment wildcard crossing ‘/’STRING — Path to testReturns: BOOL — True when the whole of p matches the whole pattern
Examples:
(Path match? "*.x" "file.x") => #t
(Path match? "lib/*.x" "lib/a/b.x") => #f
(Path match? "lib/**/*.x" "lib/a/b.x") => #t
(Path match? "lib/**" "lib") => #t