Skip to content

Path and PathBuf

Level: 201 · working knowledge

One line: Path is to PathBuf what &str is to String — borrowed against owned — and a function that takes impl AsRef<Path> accepts all four spellings without the caller converting anything.

Stub — an outline, not a lesson. There is no runnable example behind this page yet, so nothing on it has been through the check that backs every other claim in this library. The bullets below are the questions the finished page has to answer.

What it has to cover

  • Why a path is not a String: on Unix a filename is bytes, on Windows it is UTF-16, and neither is guaranteed to be valid UTF-8 — hence OsStr underneath
  • The way down and the way out: as_os_str / into_os_string hand you that OsStr / OsString unchanged, and to_str / to_string_lossy are where you decide what a non-UTF-8 path turns into — the same two exits Six kinds of string shows for OsStr
  • The consequence you meet first: println!("{}", path) does not compile; path.display() is the escape hatch and it is lossy on purpose
  • join and push, and the sharp edge — joining an absolute path discards everything to its left
  • The parts: file_name, file_stem, extension, parent, and the fact that each returns an Option
  • AsRef<Path> as the shape of a good API, and what generic argument actually does at the call site

The trap it exists for

base.join(user_input) looks like string concatenation and is not. If the input is /etc/passwd, the result is /etc/passwd — the base is gone. That is a path-traversal bug written in one method call, in a language people reach for because it is careful.

See also

Po polsku

Path ma się do PathBuf tak, jak wycinek łańcucha &str do String: pierwszy jest pożyczony, drugi trzyma dane na własność. Osobny typ nie jest kaprysem — ścieżka nie jest łańcuchem znaków, bo nazwa pliku to na Uniksie ciąg bajtów, a w Windowsie UTF-16, i żadna z nich nie musi być poprawnym UTF-8. Polski czytelnik trafia na to szybciej niż inni: plik sprawozdanie_ąćę.txt przyniesiony ze starego dysku w Latin-2 albo CP-1250 jest dokładnie taką nazwą, której nie da się przedstawić jako String — dlatego pod spodem siedzi OsStr, dlatego println!("{}", path) się nie kompiluje, a path.display() jest wyjściem awaryjnym, które świadomie gubi to, czego nie umie pokazać. Drugą pułapką jest join, które nie jest sklejaniem łańcuchów: gdy base.join(dane_od_użytkownika) dostanie ścieżkę bezwzględną, zaczynającą się od / albo od C:\, baza po prostu znika z wyniku — i tak w jednym wywołaniu metody powstaje podatność typu path traversal.

Szukaj po polsku: ścieżki w Ruscie · nazwa pliku spoza UTF-8 · rust Path vs PathBuf · rust PathBuf join absolute path · rust AsRef<Path> parameter