在Windows上,Path::canonicalize()
以以下格式返回路径:
\\\\?\\C:\\projects\\3rdparty\\rust...
这是因为它是正确的规范路径,并允许在Windows上使用“长”路径(请参阅Why does my canonicalized path get prefixed with \\?\)。
然而,这不是一个用户友好的路径,人们不理解它。
对于显示和记录目的,如何以通用平台无关的方式轻松删除此前缀?
Path::components
将返回组件\\?\C:
作为第一个组件...
我应该将其转换为&str
并使用正则表达式吗?是否有一些其他更符合人体工程学的方法来删除前缀,例如某种类型的Display
实现会自动执行正确的操作吗?
我的具体要求是:
X:\\...
规范路径。示例:
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);
}
答案 0 :(得分:3)
直截了当的答案是进行特定于平台的字符串修改:
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);
}
为了记录,我并不同意你的前提是个好主意。 Windows资源管理器处理这些逐字路径就好了,我认为用户也能够处理它。
用于[...]记录目的
这听起来像个糟糕的主意。如果您要记录某些内容,则需要知道完全路径,而不是某些可能不正确的路径。
答案 1 :(得分:2)
extern crate dunce;
…
let compatible_path = dunce::canonicalize(&any_path);
正在剥离\\?\
可能会提供错误/无效的路径。 dunce crate检查UNC路径是否兼容并尽可能准确地转换路径。它通过所有其他路径。它在非Windows上编译为普通fs::canonicalize()
。