gpt4 book ai didi

rust - std::fs::canonicalize 不存在的文件

转载 作者:行者123 更新时间:2023-12-04 12:55:17 51 4
gpt4 key购买 nike

我正在用 Rust 编写一个程序,它在用户定义的路径上创建一个文件。我需要能够规范化中间组件( ~/ 应该变成 $HOME/../ 应该进入目录等)以便在正确的位置创建文件。 std::fs::canonicalize几乎完全符合我的要求,但如果路径不存在,它会 panic 。
是否有一个函数可以以与 std::fs::canonicalize 相同的方式规范化组件但如果文件不存在,不会 panic ?

最佳答案

这样的功能不标准是有充分理由的:

  • 当您同时处理链接和不存在的文件时,没有唯一的路径。如 a/b是指向 c/d/e 的链接,然后 a/b/../f可能意味着 a/fc/d/f
  • ~快捷方式是 shell 功能。您可能想对其进行概括(我愿意),但这是一个不明显的选择,尤其是当您考虑 ~ 时。在大多数系统中是一个有效的文件名。

  • 话虽如此,但在某些情况下,由于应用程序的性质,这些歧义不是问题,它有时很有用。
    这是 what I do在这种情况下:
    use {
    directories::UserDirs,
    lazy_regex::*,
    std::path::{Path, PathBuf},
    };

    /// build a usable path from a user input which may be absolute
    /// (if it starts with / or ~) or relative to the supplied base_dir.
    /// (we might want to try detect windows drives in the future, too)
    pub fn path_from<P: AsRef<Path>>(
    base_dir: P,
    input: &str,
    ) -> PathBuf {
    let tilde = regex!(r"^~(/|$)");
    if input.starts_with('/') {
    // if the input starts with a `/`, we use it as is
    input.into()
    } else if tilde.is_match(input) {
    // if the input starts with `~` as first token, we replace
    // this `~` with the user home directory
    PathBuf::from(
    &*tilde
    .replace(input, |c: &Captures| {
    if let Some(user_dirs) = UserDirs::new() {
    format!(
    "{}{}",
    user_dirs.home_dir().to_string_lossy(),
    &c[1],
    )
    } else {
    warn!("no user dirs found, no expansion of ~");
    c[0].to_string()
    }
    })
    )
    } else {
    // we put the input behind the source (the selected directory
    // or its parent) and we normalize so that the user can type
    // paths with `../`
    normalize_path(base_dir.join(input))
    }
    }


    /// Improve the path to try remove and solve .. token.
    ///
    /// This assumes that `a/b/../c` is `a/c` which might be different from
    /// what the OS would have chosen when b is a link. This is OK
    /// for broot verb arguments but can't be generally used elsewhere
    ///
    /// This function ensures a given path ending with '/' still
    /// ends with '/' after normalization.
    pub fn normalize_path<P: AsRef<Path>>(path: P) -> PathBuf {
    let ends_with_slash = path.as_ref()
    .to_str()
    .map_or(false, |s| s.ends_with('/'));
    let mut normalized = PathBuf::new();
    for component in path.as_ref().components() {
    match &component {
    Component::ParentDir => {
    if !normalized.pop() {
    normalized.push(component);
    }
    }
    _ => {
    normalized.push(component);
    }
    }
    }
    if ends_with_slash {
    normalized.push("");
    }
    normalized
    }
    (这使用 directories crate 以跨平台方式获取主页,但存在其他 crate ,您也可以在大多数平台上读取 $HOME 环境变量)

    关于rust - std::fs::canonicalize 不存在的文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68231306/

    51 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com