Rust:如何扩展路径、连接路径和 glob 文件?

Rust: How to expand path, join path, and glob files?

我正在学习 Rust,我正在尝试转换一个简单的 Ruby 示例,该示例执行以下操作:

  1. File expand path
  2. File join paths
  3. Dir glob
  4. 打印在 Dir glob 中找到的文件

这是 Ruby 示例:

output_path = '~/Documents'
pattern = File.expand_path(File.join(output_path, '*', '**', '*.txt'))

Dir.glob(pattern) do |path|
  puts path
end

Bonus Nim 示例:

import os
import strformat
import glob

var outputPath = expandTilde("~/Documents")
var pattern = joinPath(outputPath, "*", "**", "*.txt")

for path in walkGlob(pattern):
  echo path

这是我到目前为止对 Rust 的了解,但是,它没有构建:

use std::io;
use std::fs;
use std::path::PathBuf;
use glob::glob;

fn main() {
    let output_path: io::Result<PathBuf> = fs::canonicalize("~/Documents");
    let pattern: PathBuf = [output_path, "*", "**", "*.txt"].iter().collect();
    for entry in glob(pattern).expect("Failed to read glob pattern") {
        match entry {
            Ok(path) => println!("{:?}", path.display()),
            Err(e) => println!("{:?}", e),
        }
    }
}

我尝试了不同的变体但没有成功。

我不确定 fs::canonicalize actually expands tilde paths. I found an older crate which does: shellexpand::tilde。但是,我不知道如何处理它给出的输出。这不是 strString

我也不确定我是否需要 ResultOption return 中某些值的多个 match 级别。最终 glob 想要一个 str,而在我所有的变体中,第一个 output_path 值搞砸了,或者我不知道如何将其转换为 str

我错过了什么?这样做的惯用方法是什么?到目前为止,我尝试过的方法似乎过于冗长。有没有简单的方法可以做到这一点?

更新

如果我对扩展路径进行硬编码,我最终可以使用它:

use std::path::PathBuf;
use glob::glob;

fn main() {
    let pattern_path_buf: PathBuf = ["", "/Users", "ejstembler", "Documents", "*", "**", "*.txt"].iter().collect();
    match pattern_path_buf.to_str() {
        Some(pattern) => {
            println!("{:?}", pattern);
            for entry in glob(pattern).expect("Failed to read glob pattern") {
                match entry {
                    Ok(path) => println!("{:?}", path.display()),
                    Err(e) => println!("{:?}", e),
                }
            }
        },
        None => println!("no pattern_path_buf")
    }
}

一个奇怪的细微差别是,我必须在 PathBuf "" 的开头添加一个空白字符串,以使其包含前导正斜杠,否则它会丢失。我发现有 std::path::MAIN_SEPARATOR,但是,我不知道如何将 char 转换为 &str

无论如何,@Joe_Jingyu provided the accepted shellexpand::tilde 一起工作。谢谢乔!

这是我使用 shellexpand::tilde 扩展波浪号的代码。

use std::path::PathBuf;
use glob::glob;
use shellexpand;

fn main() {
    let expanded_path = shellexpand::tilde("~/Documents/");
    let pattern : PathBuf = [&expanded_path, "*", "**", "*.txt"].iter().collect();

    for entry in glob(pattern.to_str().unwrap()).expect("Failed to read glob pattern") {
        match entry {
            Ok(path) => println!("{:?}", path.display()),
            Err(e) => println!("{:?}", e),
        }
    }
}

这里是 如何从 shellexpand::tilde.

返回的 Cow 中获取 &str