Path 习惯性地在生锈路径中展开瓷砖

Path 习惯性地在生锈路径中展开瓷砖,path,rust,directory,home-directory,Path,Rust,Directory,Home Directory,有时,例如,在读取某些配置文件时,您读取用户输入的文件路径而不经过shell(例如,您得到~/test) 由于下面的选项2没有写入用户主目录中的测试文件,我想知道是否有比选项1更惯用的东西 使用std::env::var; 使用std::fs::File; 使用std::io::prelude::*; 使用std::path::path; fn写入到(路径:&路径){ 让mut f=File::create(path).unwrap(); f、 全部写入(“Hi”。作为字节())。展开(); }

有时,例如,在读取某些配置文件时,您读取用户输入的文件路径而不经过shell(例如,您得到
~/test

由于下面的
选项2
没有写入用户主目录中的测试文件,我想知道是否有比
选项1
更惯用的东西

使用std::env::var;
使用std::fs::File;
使用std::io::prelude::*;
使用std::path::path;
fn写入到(路径:&路径){
让mut f=File::create(path).unwrap();
f、 全部写入(“Hi”。作为字节())。展开();
}
fn main(){
//选择1
let from_env=format!(“{}/test”,var(“HOME”).unwrap();
let with_var=Path::new(&from_env);
//创建$HOME/test
写入(带有变量);
//选择2
使用_tilde=Path::new(“~/test”)的let;
//在当前目录中创建测试文件,前提是存在一个目录。/~存在
写入(用波浪号);
}
注意
unwrap()
用于简化示例。生产代码中应该有一些错误处理

  • 最惯用的方法是只使用现有的板条箱,在这种情况下,
    shellexpand
    (,)似乎可以做您想要做的事情:

    extern crate shellexpand; // 1.0.0
    
    #[test]
    fn test_shellexpand() {
        let home = std::env::var("HOME").unwrap();
        assert_eq!(shellexpand::tilde("~/foo"), format!("{}/foo", home));
    }
    
  • 或者,您可以使用
    dirs
    ()进行尝试。这是一张草图:

    extern crate dirs; // 1.0.4
    
    use std::path::{Path, PathBuf};
    
    fn expand_tilde<P: AsRef<Path>>(path_user_input: P) -> Option<PathBuf> {
        let p = path_user_input.as_ref();
        if !p.starts_with("~") {
            return Some(p.to_path_buf());
        }
        if p == Path::new("~") {
            return dirs::home_dir();
        }
        dirs::home_dir().map(|mut h| {
            if h == Path::new("/") {
                // Corner case: `h` root directory;
                // don't prepend extra `/`, just drop the tilde.
                p.strip_prefix("~").unwrap().to_path_buf()
            } else {
                h.push(p.strip_prefix("~/").unwrap());
                h
            }
        })
    }
    
    一些评论:

    • P:AsRef
      输入类型模仿标准 图书馆有。这就是为什么该方法接受所有的
      Path
      -like 输入,如
      &str
      &OsStr
      ,和
      &Path
    • Path::new
      不分配任何内容,它指向 与
      &str
      完全相同的字节
    • strip\u前缀(“~/”).unwrap()
      在这里永远不会失败, 因为我们检查了路径以
      ~
      和开头 不仅仅是
      ~
      。唯一的办法就是 路径以
      ~/
      开头(因为
      开头)
      定义了)
  • #[test]
    fn test_expand_tilde() {
        // Should work on your linux box during tests, would fail in stranger
        // environments!
        let home = std::env::var("HOME").unwrap();
        let projects = PathBuf::from(format!("{}/Projects", home));
        assert_eq!(expand_tilde("~/Projects"), Some(projects));
        assert_eq!(expand_tilde("/foo/bar"), Some("/foo/bar".into()));
        assert_eq!(
            expand_tilde("~alice/projects"),
            Some("~alice/projects".into())
        );
    }