You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Add function to make paths absolute, which is different from canonicalization #59117
Many users want to turn relative paths into absolute paths, but the only tool that libstd currently offers is canonicalize which is bad because it has to hit the filesystem which has several downsides:
It takes time to hit the filesystem.
The path has to actually exist.
It fails on certain types of drives such as RAM drives on Windows.
The path it creates is a \\?\ path which not all software can handle correctly and imposes requirements on further path manipulation that few users are even aware of.
Needing symbolic links actually resolved is an extremely rare use case, and is often misused to compare paths for equality when in reality you should be comparing file IDs due to things like hard links existing.
A new function (normalize or make_absolute or something, bikeshed away) should be added that will turn a relative path into an absolute path without touching the filesystem. On Windows this should either call GetFullPathNameW or do the pure Rust equivalent while on unixy platforms... something should happen, I have no idea.
One big question for the libs team to decide on is how to handle .. and . on linux. On Windows C:\foo\..\bar is equivalent to C:\bar and both paths will always point to the same thing. On linux however it is possible for /foo/../bar to not point to the same thing as /bar. Given a current directory of /foo and a relative path of ../bar, should normalize on linux return /foo/../bar or /bar?
Some prior art might be the Node path.normalize function which (it seems?) doesn't hit the FS and just tries to do the reasonable thing given path structure, e.g.:
I guess fs::canonicalize() is like realpath -e and the requested feature is like realpath -ms on Linux.
I want to reiterate that fs::normalize() should not be used for this, but for rust-lang/rfcs#2208 which is different from both of these. It doesn't account for CWD and leaves relative paths relative, making it the proper equivalent of Node's path.normalize() referenced above.
Reacted by Evsyukov Denis, Aetf, Stephan Sokolow, hoijui and Michael Diamond
changed the title [-]Add function to normalize paths, which is different from canonicalization[/-][+]Add function to make paths absolute, which is different from canonicalization[/+]on Jul 14, 2020
I think this should be mentioned here too, @dylni has created a normpath crate to do pretty much this: https://crates.io/crates/normpath it seems to also call the GetFullPathNameW on Windows, and doesn't hit the disk.
To clarify, PathExt::normalize only doesn't touch the filesystem on Windows. On Unix, it needs to canonicalize the path to resolve it correctly. Canonical Unix paths don't have the same issues as verbatim paths on Windows.
@MouseProducedGames Note that it only fails on improperly implemented RAM disk software (unfortunately this includes at least one rather popular one). Something well made, like Radeon RAMDisk, should work fine.
@MouseProducedGames Note that it only fails on improperly implemented RAM disk software (unfortunately this includes at least one rather popular one). Something well made, like Radeon RAMDisk, should work fine.
That is good to know; and thanks for the recommendation.
It fails on certain types of drives such as RAM drives on Windows.
This appears to be fixed in the latest Windows 11 updates. I have tested calling canonicalize on (improperly implemented) ramdisk and network drive, and it no longer returns "Incorrect function". Could anyone verify it?
@gyk Do you have a version number? 10.0.22621 still fails last I checked (e.g. with ImDisk). Though I admit I haven't checked the latest Beta or Preview channels.
@ChrisDenton The OS builds are 22623.1325 (beta channel) and 22621.1105. The ramdisk software I tested was Ultra RAMDisk Lite (IIRC it didn't work before?), I just tried it again with ImDisk and yes, it still failed. And canonicalize now works on network drives mapped to QNAP or Synology NAS and I'm certain it used to return IO errors.
the difference is to only prepend current_dir when input path is absolute, but when input path is relative, should result in relative:
currently it's not hard to call one extra Path::strip_prefix of current_dir:
let normed = path::absolute(inpath).map(|full| {if inpath.is_relative(){PathBuf::from(full.strip_prefix(env::current_dir()?).expect("strip_prefix"))}else{
full
}}).expect("normed");println!("{} normed to: {}", strip_prefix.display(), normed.display());
Should I make a feature request (and a PR) for path::normalize in Rust?
@tx0c A path::normalize that will resolve .. and convert path separators, but without necessarily making the path an absolute path, sounds like a great idea. That said, I believe the unstable Path::normalize_lexically is already quite close to what you are requesting. Perhaps you should investigate whether that is what you want and if not, should that function be changed or should there be a separate function? #134694
Activity
Mark-Simulacrum commentedon Mar 12, 2019
Semi-related issues/PRs: #47402, #47363, and rust-lang/rfcs#2208.
retep998 commentedon Mar 24, 2019
One big question for the libs team to decide on is how to handle
..and.on linux. On WindowsC:\foo\..\baris equivalent toC:\barand both paths will always point to the same thing. On linux however it is possible for/foo/../barto not point to the same thing as/bar. Given a current directory of/fooand a relative path of../bar, shouldnormalizeon linux return/foo/../baror/bar?Xanewok commentedon Apr 9, 2019
Some prior art might be the Node
path.normalizefunction which (it seems?) doesn't hit the FS and just tries to do the reasonable thing given path structure, e.g.:[hack] avoid directly using mounted volumes
nayeemrmn commentedon Sep 7, 2019
A function called
normalize()will not be expected to convert to an absolute path, that name should be used for rust-lang/rfcs#2208.nayeemrmn commentedon Dec 6, 2019
I guess
fs::canonicalize()is likerealpath -eand the requested feature is likerealpath -mson Linux.I want to reiterate that
fs::normalize()should not be used for this, but for rust-lang/rfcs#2208 which is different from both of these. It doesn't account for CWD and leaves relative paths relative, making it the proper equivalent of Node'spath.normalize()referenced above.[-]Add function to normalize paths, which is different from canonicalization[/-][+]Add function to make paths absolute, which is different from canonicalization[/+]Ciantic commentedon Jan 12, 2021
I think this should be mentioned here too, @dylni has created a
normpathcrate to do pretty much this: https://crates.io/crates/normpath it seems to also call theGetFullPathNameWon Windows, and doesn't hit the disk.dylni commentedon Jan 13, 2021
Thanks @Ciantic!
To clarify,PathExt::normalizeonly doesn't touch the filesystem on Windows. On Unix, it needs to canonicalize the path to resolve it correctly. Canonical Unix paths don't have the same issues as verbatim paths on Windows.PathExt::normalize_virtuallyfrom that crate can be used to normalize paths without touching the filesystem, butPathExt::normalizeis usually what you want.MouseProducedGames commentedon May 6, 2021
"It fails on certain types of drives such as RAM drives on Windows."
Being able to compile on a RAM drive on Windows, would save a lot of SSD thrashing.
ChrisDenton commentedon May 7, 2021
@MouseProducedGames Note that it only fails on improperly implemented RAM disk software (unfortunately this includes at least one rather popular one). Something well made, like Radeon RAMDisk, should work fine.
MouseProducedGames commentedon May 7, 2021
That is good to know; and thanks for the recommendation.
Rollup merge of rust-lang#91673 - ChrisDenton:path-absolute, r=Mark-S…
3 remaining items
andylizi commentedon Feb 17, 2022
Should this be closed now that #91673 is merged?
gyk commentedon Feb 26, 2023
This appears to be fixed in the latest Windows 11 updates. I have tested calling
canonicalizeon (improperly implemented) ramdisk and network drive, and it no longer returns "Incorrect function". Could anyone verify it?ChrisDenton commentedon Feb 26, 2023
@gyk Do you have a version number? 10.0.22621 still fails last I checked (e.g. with ImDisk). Though I admit I haven't checked the latest Beta or Preview channels.
gyk commentedon Feb 26, 2023
@ChrisDenton The OS builds are 22623.1325 (beta channel) and 22621.1105. The ramdisk software I tested was Ultra RAMDisk Lite (IIRC it didn't work before?), I just tried it again with ImDisk and yes, it still failed. And
canonicalizenow works on network drives mapped to QNAP or Synology NAS and I'm certain it used to return IO errors.tx0c commentedon Mar 15, 2025
Yeah, the Node [
path.normalize] behavior has one more difference and is exactly I wanted: when to normalize a relative path:the difference is to only prepend current_dir when input path is absolute, but when input path is relative, should result in relative:
currently it's not hard to call one extra
Path::strip_prefixof current_dir:Should I make a feature request (and a PR) for
path::normalizein Rust?retep998 commentedon Mar 9, 2026
@tx0c A
path::normalizethat will resolve..and convert path separators, but without necessarily making the path an absolute path, sounds like a great idea. That said, I believe the unstablePath::normalize_lexicallyis already quite close to what you are requesting. Perhaps you should investigate whether that is what you want and if not, should that function be changed or should there be a separate function?#134694
bardiharborow commentedon Aug 24, 2026
This can be closed since
std::path::absolutewas stabilized in #92750.@rustbot label +A-io