我认为这应该是很容易做到的,因为有一个好用的函数canonicalize
可以规范化路径(所以我可以通过规范化我的两个输入路径来开始),Path
和PathBuf
可以通过components
提供一种迭代路径部件的方法。我想在这里可以想出一些方法来分解公共前缀,然后将锚路径中剩余的每个 ..
部件添加到初始输入路径的剩余部分。
我的问题似乎相当普遍:
我认为这应该是很容易做到的,因为有一个好用的函数canonicalize
可以规范化路径(所以我可以通过规范化我的两个输入路径来开始),Path
和PathBuf
可以通过components
提供一种迭代路径部件的方法。我想在这里可以想出一些方法来分解公共前缀,然后将锚路径中剩余的每个 ..
部件添加到初始输入路径的剩余部分。
我的问题似乎相当普遍:
现在这段代码已经作为pathdiff
包存在,使用的是来自kennytm回答中的代码
你可以这样使用它:
extern crate pathdiff;
pathdiff::diff_paths(path, base);
base
是应用相对路径以获取path
的位置。
Path::strip_prefix
,但它不会为你计算 ../
(而是返回一个错误):use std::path::*;
let base = Path::new("/foo/bar");
let child_a = Path::new("/foo/bar/a");
let child_b = Path::new("/foo/bar/b");
println!("{:?}", child_a.strip_prefix(base)); // Ok("a")
println!("{:?}", child_a.strip_prefix(child_b)); // Err(StripPrefixError(()))
< p >之前的 < code >strip_prefix 版本是 < code >path_relative_from,它曾经添加 < code >../,但由于符号链接 此行为已被取消,现在有了新的行为:
< blockquote >
< ol >
// This routine is adapted from the *old* Path's `path_relative_from`
// function, which works differently from the new `relative_from` function.
// In particular, this handles the case on unix where both paths are
// absolute but with only the root as the common directory.
fn path_relative_from(path: &Path, base: &Path) -> Option<PathBuf> {
use std::path::Component;
if path.is_absolute() != base.is_absolute() {
if path.is_absolute() {
Some(PathBuf::from(path))
} else {
None
}
} else {
let mut ita = path.components();
let mut itb = base.components();
let mut comps: Vec<Component> = vec![];
loop {
match (ita.next(), itb.next()) {
(None, None) => break,
(Some(a), None) => {
comps.push(a);
comps.extend(ita.by_ref());
break;
}
(None, _) => comps.push(Component::ParentDir),
(Some(a), Some(b)) if comps.is_empty() && a == b => (),
(Some(a), Some(b)) if b == Component::CurDir => comps.push(a),
(Some(_), Some(b)) if b == Component::ParentDir => return None,
(Some(a), Some(_)) => {
comps.push(Component::ParentDir);
for _ in itb {
comps.push(Component::ParentDir);
}
comps.push(a);
comps.extend(ita.by_ref());
break;
}
}
}
Some(comps.iter().map(|c| c.as_os_str()).collect())
}
}