🍣
[Rust] Path に glob がなかったので外部クレートの glob と globmatch を使ってみた
はじめに
ファイルを収集するとき Ruby では Pathname.glob
があった。
でも Rust の Path には glob がなくてがっかりだった。
そこで外部クレートで見つけた次の2つを使ってみる。
まずディレクトリ構成は次のようになっている。
$ exa -T a
a
└── b
└── c
├── 1.png
├── 2.png
└── 3.PNG
glob 編
簡単な使い方
use glob::glob;
let files = glob("a/**/*.png")
.unwrap()
.map(|e| e.unwrap())
.collect::<Vec<_>>();
println!("{:?}", files);
// >> ["a/b/c/1.png", "a/b/c/2.png"]
3.PNG
が出てきていないのは大小文字を区別するようになっているから。
そういうときは a/**/*.{png,PNG}
と書けば PNG にもマッチするもんだけど動かなかった (なんで?)
大小文字の区別をやめる
use glob::glob_with;
use glob::MatchOptions;
let mut options = MatchOptions::new();
options.case_sensitive = false; // false:大小文字の区別をしない
let files = glob_with("a/**/*.png", options)
.unwrap()
.map(|e| e.unwrap())
.collect::<Vec<_>>();
println!("{:?}", files);
// >> ["a/b/c/1.png", "a/b/c/2.png", "a/b/c/3.PNG"]
case_sensitive
を false
にしたことで png
でも PNG
にマッチするようになったのがわかる。
できれば case_sensitive: false
を初期値にしといてほしかった(小声)
globmatch 編
簡単な使い方
let files = globmatch::Builder::new("a/**/*.{png,PNG}")
.build(".")
.unwrap()
.into_iter()
.flatten()
.collect::<Vec<_>>();
// files は PathBuf の配列
println!("{:?}", files);
// >> ["./a/b/c/2.png", "./a/b/c/3.PNG", "./a/b/c/1.png"]
こちらも大小文字区別ありが初期値となっているけど a/**/*.{png,PNG}
と書ける!
その点で言えばこっちの方が使いやすそう。
Discussion