Reputation: 2042
I'm learning Rust and I'm trying to convert a simple Ruby example which does:
Here's the Ruby example:
output_path = '~/Documents'
pattern = File.expand_path(File.join(output_path, '*', '**', '*.txt'))
Dir.glob(pattern) do |path|
puts path
end
Bonus Nim example:
import os
import strformat
import glob
var outputPath = expandTilde("~/Documents")
var pattern = joinPath(outputPath, "*", "**", "*.txt")
for path in walkGlob(pattern):
echo path
Here's what I have so far for Rust, however, it doesn't build:
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),
}
}
}
I've tried different variations with no success.
I'm not sure fs::canonicalize actually expands tilde paths. I found an older crate which does: shellexpand::tilde. However, I don't know how to deal with the output it gives. It's not a str
or String
.
I'm also not sure if I need multiple levels of match
on the Result
and Option
return values from some of those. Ultimately glob
wants a str
and in all my variations, the first output_path
value messes that up, or I don't know how to convert that to a str
.
What am I missing? What is the idiomatic way to do this? So far the approaches I've tried seem too verbose. Is there a simple way to do this?
UPDATE
I eventually got it to work if I hard-coded the expanded path:
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")
}
}
One weird nuance, is that I had to add a blank string in the beginning of the PathBuf "" to get it to include a leading forward slash, otherwise it would be missing. I found that there's std::path::MAIN_SEPARATOR
, however, I have no idea how to convert a char
to a &str
.
In any case, @Joe_Jingyu provided the accepted answer with shellexpand::tilde
working. Thanks Joe!
Upvotes: 1
Views: 2076
Reputation: 1279
Here is my code of using shellexpand::tilde to expand 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),
}
}
}
Here is a post on how to get &str from a Cow returned from shellexpand::tilde.
Upvotes: 4