如何在 Rust 中更改 &Path 的第一个祖先?
How do I change a &Path's first ancestor in Rust?
我想更改 &Path
的第一个祖先,可能是通过像这样返回一个新的 PathBuf
。
fn change_parent(path: &Path, new_parent: &Path) -> PathBuf;
这是我期望它的工作方式。
let old_path = change_root(Path::new("/hello/world.html"), Path::new("/html"));
let new_path = PathBuf::from("/html/world.html");
assert_eq!(old_path, new_path)
我试过 .ancestors()
但 Path::new("/hello/world.html").ancestors();
returns 是 ["/hello/world.html", "/hello", "/"]
上的迭代器,这与我想要的相反。我想要的是 ["/hello/world.html", "hello/world.html", "/world.html"]
这样我就可以轻松地附加一条新路径。
我是否应该在 "(/|\)"
上改用 split
然后替换第一个结果?
使用 Path::components 我想出了这个解决方案:
use std::path::{Component, Path};
use std::{ffi::OsString, path::PathBuf};
let path = Path::new("/tmp/foo.txt");
let mut b: Vec<_> = path.components().collect();
// b[0] is the root directory "/" and b[1] is the
// "tmp" directory.
let html = OsString::from("html");
b[1] = Component::Normal(&html);
let pb: PathBuf = b.iter().collect();
我找不到更简单的方法来执行此操作。 Path
和 PathBuf
实现都基于单个 OsString
。因此,对于这两种类型,要访问路径中的各个组件,底层 OsString
需要被某些东西拆分,而 components
是进行拆分的方法。所以,我不认为真的有另一种解决方案。
这是使用 Rust 编程语言社区 (Discord) 上的 conradludgate 提供的 strip_prefix
:
use std::path::{Path, PathBuf, StripPrefixError};
fn replace_prefix(p: impl AsRef<Path>, from: impl AsRef<Path>, to: impl AsRef<Path>) -> Result<PathBuf, StripPrefixError> {
p.as_ref().strip_prefix(from).map(|p| to.as_ref().join(p))
}
(
replace_prefix("/public/file.html", "/public", "/.html_output"),
replace_prefix("/public/folder/nested/file.html", "/public", "/.html_output"),
replace_prefix("/folder/nested/file.html", "/public", "/.html_output"),
)
(Ok("/.html_output/file.html"), Ok("/.html_output/folder/nested/file.html"), Err(StripPrefixError(())))
我想更改 &Path
的第一个祖先,可能是通过像这样返回一个新的 PathBuf
。
fn change_parent(path: &Path, new_parent: &Path) -> PathBuf;
这是我期望它的工作方式。
let old_path = change_root(Path::new("/hello/world.html"), Path::new("/html"));
let new_path = PathBuf::from("/html/world.html");
assert_eq!(old_path, new_path)
我试过 .ancestors()
但 Path::new("/hello/world.html").ancestors();
returns 是 ["/hello/world.html", "/hello", "/"]
上的迭代器,这与我想要的相反。我想要的是 ["/hello/world.html", "hello/world.html", "/world.html"]
这样我就可以轻松地附加一条新路径。
我是否应该在 "(/|\)"
上改用 split
然后替换第一个结果?
使用 Path::components 我想出了这个解决方案:
use std::path::{Component, Path};
use std::{ffi::OsString, path::PathBuf};
let path = Path::new("/tmp/foo.txt");
let mut b: Vec<_> = path.components().collect();
// b[0] is the root directory "/" and b[1] is the
// "tmp" directory.
let html = OsString::from("html");
b[1] = Component::Normal(&html);
let pb: PathBuf = b.iter().collect();
我找不到更简单的方法来执行此操作。 Path
和 PathBuf
实现都基于单个 OsString
。因此,对于这两种类型,要访问路径中的各个组件,底层 OsString
需要被某些东西拆分,而 components
是进行拆分的方法。所以,我不认为真的有另一种解决方案。
这是使用 Rust 编程语言社区 (Discord) 上的 conradludgate 提供的 strip_prefix
:
use std::path::{Path, PathBuf, StripPrefixError};
fn replace_prefix(p: impl AsRef<Path>, from: impl AsRef<Path>, to: impl AsRef<Path>) -> Result<PathBuf, StripPrefixError> {
p.as_ref().strip_prefix(from).map(|p| to.as_ref().join(p))
}
(
replace_prefix("/public/file.html", "/public", "/.html_output"),
replace_prefix("/public/folder/nested/file.html", "/public", "/.html_output"),
replace_prefix("/folder/nested/file.html", "/public", "/.html_output"),
)
(Ok("/.html_output/file.html"), Ok("/.html_output/folder/nested/file.html"), Err(StripPrefixError(())))