Path and PathBuf
`Path` is the borrowed, unsized counterpart to `&str`; `PathBuf` is the owned, growable counterpart to `String`. Both wrap an `OsStr` so they can hold non-UTF-8 paths on Unix and UTF-16 paths on Windows transparently. Take `impl AsRef<Path>` in function parameters; return `PathBuf` when you must own the result.
join, push, parent, file_name, extension
`join` returns a new PathBuf with another component appended, handling the OS separator. `push` mutates in place. `parent` strips the final component. `file_name` returns the final component, `file_stem` strips the extension, `extension` returns just the extension. They're all the right level of abstraction over the platform's separator differences.
For deeper background, see a complete cheat-sheet of std collection complexities for the broader context behind this section.
Canonicalisation
`Path::canonicalize` resolves `.`, `..`, and symlinks, returning the absolute real path. It hits the file system and can fail. For a purely lexical (no I/O) cleanup, the `path-clean` crate or `Path::components().collect()` works.
Comparing and matching
Path comparison is byte-for-byte after the platform's normalisation rules — it does not resolve symlinks or case-folding. For glob-pattern matching, the `globset` or `wax` crates handle `*`, `**`, and `?`. For file-extension dispatching, `Path::extension` plus a match is usually enough.
For deeper background, see the official Rust API guidelines for module-level design for the broader context behind this section.
Common pitfalls
Joining an absolute path replaces the existing prefix: `Path::new("/foo").join("/bar")` is `/bar`. Be careful when joining user input. On Windows, paths starting with `\\?\` are length-uncapped but disable some normalisation — use them for very long paths but understand the tradeoff.