`PathBuf` values are equal on Windows but not on Linux due to mismatched slashes

I have two paths in my tests. The first one uses only escaped forward slashes ("\"). The second one uses a mix of escaped forward slashes and regular backslashes ("/").
On Windows, assert_eq passes when these two paths are compared.
But when running in CI, on Linux, it fails. It also presumably fails on MacOS and other Unix-like systems.

Naturally I understand this is some platform specific behavior internally, but my question is why is this the case, and is this the intended behavior? On Windows, Rust clearly goes out of its way to ignore mismatched slashes, but not on Linux.

Complete Example:

let path_a = PathBuf::from("C:\\path/to\\example/thingy");
let path_b = PathBuf::from("C:\\path\\to\\example\\thingy");

// This passes on Windows but panics on Linux
assert_eq!(path_a, path_b);

Becuase on Linux these paths are really different. You can use \ in file names, so "back\slash" is a valid file name, not a directory. Also C: has no meaning outside Windows either, and it's just a couple of normal characters allowed anywhere in the path.

std::path is system-specific, and has a completely different implementation on Windows and other platforms.

Unfortunately, the standard library doesn't have a cross-platform path abstraction. For this you need other crates, like:

6 Likes

To expand on @kornelski answer, on Linux (and most other Unixes) the only special characters in file names is the forward slash (separator) and ASCII nul byte. Additionally the path component .. and . have special meaning (parent and current directory). That's it. You can have a file name with a literal newline in it if you want.

The path components are otherwise just byte arrays. No encoding interpretation enforced (though commonly treated as UTF-8 these days).

I believe Mac OS X has/had a few more limitations: : was forbidden on HFS+ (that used to be the path separator back in the 90s on the non-Unix Mac OS), and there is a specific encoding.

3 Likes

macOS allows : in paths, but renders it as / in the GUI. This is because in the classic MacOS : was a path separator, and / was a legal character. In Finder you can still rename a file to a name with / in it, and it will work, but use : on the "Unix" side of the OS.

3 Likes