Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I remove the \\?\ prefix from a canonical Windows path?

Tags:

windows

rust

On Windows, Path::canonicalize() returns the path in the format:

\\\\?\\C:\\projects\\3rdparty\\rust...

This is because it is the correct canonical path, and allows 'long' paths on Windows (see Why does my canonicalized path get prefixed with \\?\).

However, this is not a user-friendly path, and people do not understand it.

For display and logging purposes how can I easily remove this prefix in a generic platform independent way?

Path::components will return a component \\?\C: as the first component...

Should I convert this to a &str and use a regex? Is there some other more ergonomic method for removing the prefix, e.g. some type with a Display implementation that automatically does the right thing?

My requirements specifically are:

  • Correctly displays X:\\... for a canonical path on Windows.
  • Doesn't screw up non-Windows platforms (e.g. strip or change path components)

Example:

use std::path::{Path, PathBuf};

fn simple_path<P: AsRef<Path>>(p: P) -> String {
    String::from(p.as_ref().to_str().unwrap()) // <-- ?? What to do here?
}

pub fn main() {
    let path = PathBuf::from("C:\temp").canonicalize().unwrap();
    let display_path = simple_path(path);
    println!("Output: {}", display_path);
}
like image 732
Doug Avatar asked May 14 '18 03:05

Doug


1 Answers

Use the dunce crate:

extern crate dunce;
…
let compatible_path = dunce::canonicalize(&any_path);

Just stripping \\?\ may give wrong/invalid paths. The dunce crate checks whether the UNC path is compatible and converts the path accurately whenever possible. It passes through all other paths. It compiles to plain fs::canonicalize() on non-Windows.

like image 153
Kornel Avatar answered Nov 15 '22 06:11

Kornel