read_dir 関数の基本
Rust の標準モジュール std::fs の read_dir 関数 を使うと、ディレクトリ内のファイルやディレクトリを列挙することができます。
pub fn read_dir<P: AsRef<Path>>(path: P) -> Result<ReadDir>列挙結果には、カレントディレクトリ (.) や親ディレクトリ (..) は含まれないので、自然な列挙が可能です。
use std::fs;
fn main() {
let entries = fs::read_dir(".").unwrap(); // ReadDir を取得
// ループで Result<DieEntry, Error> をひとつずつ処理
for entry in entries {
// DirEntry#file_name() でファイル名(ディレクトリ名)を取得できる
println!("{:?}", entry.unwrap().file_name());
}
}"Cargo.toml"
"target"
"Cargo.lock"
".gitignore"
".git"
"src"エラーチェックする
上記ではコードを簡素化するために Result#unwrap メソッドを使っていますが、万が一 Err 値が返された場合は panic が発生してしまうので、プロダクトコードでは unwrap メソッドは使うべきではありません。
Result が Ok 値を持っているかを調べつつ、その値を取り出すには、次のように if let 構文を使用できます。
use std::fs;
fn main() {
if let Ok(entries) = fs::read_dir(".") {
for entry in entries {
if let Ok(entry) = entry {
println!("{:?}", entry.file_name());
}
}
}
}Path インスタンスを取得する
DirEntry#file_name() でファイル名 (OsString) を取得する代わりに、DirEntry#path() を使って PathBuf オブジェクトを取得できます。
PathBuf は、パス情報を扱ういろいろなメソッドを提供しています。
let path = entry.path(); // PathBuf を取得
println!("file_name = {:?}", entry.file_name());
println!("is_file = {}", path.is_file());
println!("is_dir = {}", path.is_dir());
println!("is_absolute = {}", path.is_absolute());
- 参考: ファイルやディレクトリの存在を調べる (
std::io::Path,PathBuf) - 参考: ファイルやディレクトリのパス文字列を構築/分割する (
std::path::Path,PathBuf)
ディレクトリ内のファイルリストを Vec で取得する
前述のように、Rust でディレクトリ内のファイルを列挙しようとすうと、少し面倒なコードになります。
下記のユーティリティ関数 read_dir_entries を使うと、指定したディレクトリに含まれているファイルやディレクトリの名前 (PathBuf) を Vec 形式でまとめて取得できます。
use std::{
fs, io,
path::{Path, PathBuf},
};
/** 指定したディレクトリ内のすべてのファイル(ディレクトリ)のパス情報を取得します。 */
fn read_dir_entries<P: AsRef<Path>>(path: P) -> io::Result<Vec<PathBuf>> {
let mut entries = fs::read_dir(path)?
.map(|res| res.map(|e| e.path()))
.collect::<Result<Vec<_>, io::Error>>()?;
entries.sort();
Ok(entries)
}
fn main() {
match read_dir_entries(".") {
Ok(entries) => println!("{:?}", entries),
Err(e) => eprintln!("ERROR: {}", e),
}
}
["./.git", "./.gitignore", "./Cargo.lock", "./Cargo.toml", "./src", "./target"]