x-lang

← Index

x/type/path

Pure-string pathname manipulation on the Path class.

Class Path

Pure-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:

Returns: 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:

Returns: 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:

Returns: 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:

Returns: 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:

Returns: 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:

Returns: 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:

Returns: 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:

Returns: 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:

Returns: 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:

Returns: 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