[OS]PathabstractPurely LEXICAL path manipulation over Strings. Nothing here touches the filesystem -- no stat, no symlink resolution, no requirement that a path exist -- which is what makes it safe on a path you are about to create. Filesystem access lives on [IO]File / [IO]Folder.
Whether the path is absolute (starts at a root).
[OS]Path.absolute?:'/tmp' "* -> true
The final component; '' where there is none ('/', '.', '..', ''). A trailing separator is ignored, so basename:'a/' is a.
[OS]Path.basename:'/a/b/c.txt' "* -> c.txt
Everything up to the last separator. Total, never nil (following POSIX / Python / Node): '.' for a bare name, and idempotent at the root ('/' is its own dirname), so the walk-upward idiom { p != [OS]Path.dirname:p }.whileDo: terminates.
[OS]Path.dirname:'/a/b/c.txt' "* -> /a/b
The extension WITHOUT its dot, or '' when there is none. A dotfile has no extension: '.bashrc' is a name, so extension:'.bashrc' is ''.
[OS]Path.extension:'report.tar.gz' "* -> gz
The repeated-keyword form of join: -- [OS]Path.join:'usr' join:'local' folds into one List at compile time, so this is the same method.
Join a List of String segments, left to right. An absolute segment resets the result, matching every shell: join:#('/a' '/b') is /b.
[OS]Path.join:#('usr' 'local' 'bin') "* -> usr/local/bin
Lexical normalization: collapse '.', resolve '..' against the preceding segment, squash repeated separators. Purely textual, so '..' past the root is dropped, a LEADING '..' on a relative path is kept (there is nothing to resolve it against without the filesystem), and a path that cancels to nothing -- or '' -- is '.'.
[OS]Path.normalize:'a/./b/../c' "* -> a/c
The final component with its (last) extension removed.
[OS]Path.stem:'report.tar.gz' "* -> report.tar