我有兴趣这样做的原因是因为我的路径的一部分将保持不变但我希望将其与其所有父项一起删除。
所以,如果我们说,
some/unknown/path/foo/bar/baz
我想返回
bar/baz
但期望我只知道foo/...
直接进入我关心的路径部分。
也许strip_prefix
是错误的做法,所以如果有更好的方法,我当然会感谢被指向这个方向。
答案 0 :(得分:3)
strip_prefix
将无法执行您想要的操作,因为它要求您知道要剥离的前缀。但是,您可以使用iter
获取路径组件上的迭代器,然后使用标准Iterator
方法仅从您想要的部分构建新的PathBuf
。
以下是一个示例(try it):
let p = path::Path::new("some/unknown/path/foo/bar/baz");
let q: path::PathBuf = p.iter() // iterate over path components
.skip_while(|s| *s != "foo") // skip everything before "foo"
.skip(1) // skip "foo" itself
.collect(); // collect the rest into a PathBuf
println!("{:?}", q); // prints "bar/baz"
(这将分配一个新的PathBuf
。Shepmaster's answer显示如何在不分配的情况下获取引用原始文件的&Path
。)
然后,您可以使用to_str
,to_string_lossy
或into_os_string
加OsString::into_string
来获取可以转换为String
的内容。
答案 1 :(得分:2)
虽然我认为trentcl's answer is cleaner,但值得展示一些非分配版本。
Path::strip_prefix
要使用Path::strip_prefix
,您需要知道前缀。我们可以通过沿着原始路径的parent
向上走来生成它,直到我们找到ends_with
“foo”。{/ p>
use std::path::Path;
fn thing1<P>(path: &P) -> Result<&Path, ()>
where
P: AsRef<Path> + ?Sized,
{
let original = path.as_ref();
let mut prefix = original;
while !prefix.ends_with("foo") {
prefix = match prefix.parent() {
Some(p) => p,
None => return Err(()),
};
}
original.strip_prefix(prefix).map_err(|_| ())
}
fn main() {
let x = thing1("some/unknown/path/foo/bar/baz");
println!("{:?}", x);
}
我们iterate可以通过路径,taking values while不是“foo”。一旦我们足够推进了迭代器,我们就可以得到余数as a path。
use std::path::Path;
fn thing2<P>(path: &P) -> &Path
where
P: AsRef<Path> + ?Sized,
{
let path = path.as_ref();
let mut i = path.iter();
for _ in i.by_ref().take_while(|c| *c != "foo") {}
i.as_path()
}
fn main() {
let x = thing2("some/unknown/path/foo/bar/baz");
println!("{:?}", x);
}
当“foo”不存在时,返回空路径。