Skip to content

Add function to make paths absolute, which is different from canonicalization #59117

Closed

Description

@retep998

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:

  1. It takes time to hit the filesystem.
  2. The path has to actually exist.
  3. It fails on certain types of drives such as RAM drives on Windows.
  4. 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.

If such a function did exist, rustc could start using that instead of canonicalize which would fix a whole host of issues including:
#74327
#74146
#59107
#58613
#55812
#52440
#48249
#45067
#42869

Activity

  1. Mark-Simulacrum commented on Mar 12, 2019

    @Mark-Simulacrum
    Member

    Semi-related issues/PRs: #47402, #47363, and rust-lang/rfcs#2208.

  2. retep998 commented on Mar 24, 2019

    @retep998
    ContributorAuthor

    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?

  3. Xanewok commented on Apr 9, 2019

    @Xanewok
    Contributor

    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.:

    For example, on POSIX:

    path.normalize('/foo/bar//baz/asdf/quux/..');
    // Returns: '/foo/bar/baz/asdf'
    

    On Windows:

    path.normalize('C:\\temp\\\\foo\\bar\\..\\');
    // Returns: 'C:\\temp\\foo\\'
    
  4. nayeemrmn commented on Sep 7, 2019

    @nayeemrmn

    A function called normalize() will not be expected to convert to an absolute path, that name should be used for rust-lang/rfcs#2208.

  5. nayeemrmn commented on Dec 6, 2019

    @nayeemrmn

    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.

  6. 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
  7. Ciantic commented on Jan 12, 2021

    @Ciantic

    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.

  8. dylni commented on Jan 13, 2021

    @dylni
    Contributor

    Thanks @Ciantic!

    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.

    PathExt::normalize_virtually from that crate can be used to normalize paths without touching the filesystem, but PathExt::normalize is usually what you want.

  9. MouseProducedGames commented on May 6, 2021

    @MouseProducedGames

    "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.

  10. ChrisDenton commented on May 7, 2021

    @ChrisDenton
    Member

    @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.

  11. MouseProducedGames commented on May 7, 2021

    @MouseProducedGames

    @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.

  12. added a commit that references this issue on Jan 11, 2022
  13. 3 remaining items

  14. andylizi commented on Feb 17, 2022

    @andylizi
    Contributor

    Should this be closed now that #91673 is merged?

  15. gyk commented on Feb 26, 2023

    @gyk

    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?

  16. ChrisDenton commented on Feb 26, 2023

    @ChrisDenton
    Member

    @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.

  17. gyk commented on Feb 26, 2023

    @gyk

    @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.

  18. tx0c commented on Mar 15, 2025

    @tx0c

    Some prior art might be the Node path.normalize function which

    Yeah, the Node [path.normalize] behavior has one more difference and is exactly I wanted: when to normalize a relative path:

    $ node -p 'path.normalize("a/././/b/../c/../d/e")'
    a/d/e

    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?

  19. retep998 commented on Mar 9, 2026

    @retep998
    ContributorAuthor

    @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

  20. added
    T-libsRelevant to the library team, which will review and decide on the PR/issue.
    and removed
    T-libs-api[DEPRECATED; DO NOT USE]
    on Aug 12, 2026
  21. bardiharborow commented on Aug 24, 2026

    @bardiharborow
    Contributor

    This can be closed since std::path::absolute was stabilized in #92750.

    @rustbot label +A-io

  22. added
    A-ioArea: `std::io`, `std::fs`, `std::net` and `std::path`
    on Aug 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-ioArea: `std::io`, `std::fs`, `std::net` and `std::path`C-feature-requestCategory: A feature request, i.e: not implemented / a PR.T-libsRelevant to the library team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions