如何从规范的 Windows 路径中删除 \\?\ 前缀?

Dou*_*oug 6 windows rust

在 Windows 上,Path::canonicalize()以以下格式返回路径:

\\\\?\\C:\\projects\\3rdparty\\rust...
Run Code Online (Sandbox Code Playgroud)

这是因为它是正确的规范路径,并且允许在 Windows 上使用“长”路径(请参阅为什么我的规范化路径以 \\?\ 为前缀)。

然而,这并不是一条人性化的道路,人们并不理解。

出于显示和记录目的,我如何以独立于通用平台的方式轻松删除此前缀?

Path::components将返回一个组件\\?\C:作为第一个组件...

我应该将其转换为 a&str并使用正则表达式吗?是否有其他更符合人体工程学的方法来删除前缀,例如某种带有Display实现可以自动做正确的事情?

我的要求具体是:

  • X:\\...在 Windows 上正确显示规范路径。
  • 不会搞砸非 Windows 平台(例如剥离或更改路径组件)

例子:

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);
}
Run Code Online (Sandbox Code Playgroud)

She*_*ter 7

简单的答案是进行特定于平台的字符串修改:

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

#[cfg(not(target_os = "windows"))]
fn adjust_canonicalization<P: AsRef<Path>>(p: P) -> String {
    p.as_ref().display().to_string()
}

#[cfg(target_os = "windows")]
fn adjust_canonicalization<P: AsRef<Path>>(p: P) -> String {
    const VERBATIM_PREFIX: &str = r#"\\?\"#;
    let p = p.as_ref().display().to_string();
    if p.starts_with(VERBATIM_PREFIX) {
        p[VERBATIM_PREFIX.len()..].to_string()
    } else {
        p
    }
}

pub fn main() {
    let path = PathBuf::from(r#"C:\Windows\System32"#)
        .canonicalize()
        .unwrap();
    let display_path = adjust_canonicalization(path);
    println!("Output: {}", display_path);
}
Run Code Online (Sandbox Code Playgroud)

根据记录,我不同意你的前提是个好主意。Windows 资源管理器可以很好地处理这些逐字路径,而且我认为用户也有能力处理它。

出于记录目的

这听起来是一个糟糕的主意。如果您正在记录某些内容,您想知道确切的路径,而不是一些可能不正确的路径。


Kor*_*nel 5

使用dunce箱子

extern crate dunce;
…
let compatible_path = dunce::canonicalize(&any_path);
Run Code Online (Sandbox Code Playgroud)

只是剥离\\?\可能会给出错误/无效的路径。dunce crate 检查 UNC 路径是否兼容,并尽可能准确地转换路径。它通过所有其他路径。它fs::canonicalize()在非 Windows 上编译为纯文本。