bash
$ dirsearch --number [num]
こんにちは、@ekusiadadusです。 CLI ツール作っていますか? CLI ツールを Rust で作るときに、毎回環境を整えるのが面倒だったので、テンプレを作りました。 今回はそのテンプレを使って、簡易的な CLI ツールを Rust で爆速で作ってみます。
テンプレートはこちらです。 https://github.com/ekusiadadus/rust-cli-template
今回作るコマンドラインツールはこちらです。 https://github.com/ekusiadadus/dirsearch
今回は、よくあるディレクトリ配下に存在するフォルダ、ファイルの数とその大きさを表示する CLI ツールを爆速で作ってみます。
まずは、テンプレをクローンします。
bash
git clone https://github.com/ekusiadadus/rust-cli-template.git
cargo run
で実行してみるテンプレを使うには、テンプレのディレクトリに移動して、cargo run
を実行します。
bash
cd rust-cli-template
cargo run
うまくいけば、こんな感じで、rust-cli-template
という名前の CLI ツールが実行されます。
既にこの段階で、cargo run
で CLI ツールが実行できる環境が整っています。
mold + cargo watch は使わなくてもいいですが、以下の点で便利です。
ここら辺は、参考記事を貼っておくのでもしよかったら使ってみてください。
https://keens.github.io/blog/2021/12/20/moldwotsukautorustnobirudogahayakunaru/
https://qiita.com/kyamamoto9120/items/2081bc44c6c987b9ec29
今回の場合、cargo watch -s 'mold -run cargo run'
でホットリロードできる環境にしています。
Makefile も載せてあるので、make watch
で動きます。
保存すると自動的にビルドされて、実行されます。
walkDir を使って、ディレクトリ配下のファイル、フォルダの数と大きさを表示するようにします。
walkdirをつかいます。
bash
cargo add walkdir
walkDir を使うには、use walkdir::WalkDir;
を追加します。
```rust use walkdir::WalkDir;
fn main() { for entry in WalkDir::new(".") { let entry = entry.unwrap(); println!("{}", entry.path().display()); } } ```
cargo run
で実行すると、ディレクトリ配下のファイル、フォルダが表示されます。
ディレクトリ配下のファイルと、フォルダを走査して、ファイルの数と大きさを表示するようにします。 walkdir を使うと非常に簡単にファイルとフォルダを走査できます。
```rust use walkdir::WalkDir; const DIR: &str = "./";
fn main() { let mut size: u64 = 0; let mut count: u64 = 0;
for entry in WalkDir::new(DIR).into_iter().filter_map(|e| e.ok()) {
let path = entry.path();
if path.is_file() {
size += path.metadata().unwrap().len();
count += 1;
}
println!("{}", entry.path().display());
}
println!("{} files, {} bytes", count, size);
} ```
実際にcargo run
で走らせてみるとこんな感じ。
現在のディレクトリ配下には、626 個のファイルが存在して、総合で304742935 bytes
の大きさになることがわかります。
ファイルサイズを Rust でいい感じに表示するには、file_sizeを使います。
```txt use filesize::fit4;
asserteq!(&fit4(999), "999"); asserteq!(&fit4(12345), "12K"); asserteq!(&fit4(999999), "1.0M"); asserteq!(&fit4(7155456789_012), "7.2T"); ```
こんな感じで、いい感じにファイルサイズを表示してくれるクレートです。
bash
println!("{} files, {} bytes", count, fit_4(size));
使ってみるとこんな感じ。
ええやん。
ディレクトリ配下のファイルで上位 N 件を持ってくるようにします。
あと main
が大きくなってきたので、関数に切り出します。
```rust
fn getdirsize(dir: &str) -> Result<(), Box
for entry in WalkDir::new(dir).into_iter().filter_map(|e| e.ok()) {
let path = entry.path();
if path.is_file() {
let t = path.metadata().unwrap().len();
if t > min_tops {
tops.push(Entry {
path: path.to_str().unwrap().to_string(),
size: t,
});
tops.sort_by(|a, b| b.size.cmp(&a.size));
tops.truncate(NUM);
min_tops = tops.last().unwrap().size;
}
size += path.metadata().unwrap().len();
count += 1;
}
}
println!("{} files, {} bytes", count, fit_4(size));
println!("{} largest files:", NUM);
println!("{} | {}", "Size", "Path");
for t in tops {
println!("{} | {}", fit_4(t.size), t.path);
}
Ok(())
} ```
実行するとこんな感じ。
clap v4 を使って、コマンドラインツールにします。 v4 は、v3 とはかなり違うので、clap v4 のドキュメントを見ながら進めましょう。
```rust use clap::Parser;
Cargo.toml
struct Cli { #[arg(long)] number: usize, }
fn main() { let cli = Cli::parse(); let num = cli.number; let dir = DIR;
if num == 0 {
println!("Number of files to show must be greater than 0");
return;
}
get_dir_size(dir, num).unwrap();
}
```
実際に実行するとこんな感じになります。
--number
argument を忘れると怒られます。
例えば、上位 100 件を表示するには、--number 100
とします。
デフォルトで --help
が使えるようになっています。
Cargo.toml
に書いた情報が、--help
で表示されます。
```toml [package] name = "rust-cli-template" version = "0.1.0" edition = "2021" license = "MIT" description = "🌸 Rust CLI Template using clap v4 🌸" readme = "README.md" homepage = "https://github.com/ekusiadadus/rust-cli-template" repository = "https://github.com/ekusiadadus/rust-cli-template" keywords = ["cli", "Japan", "Rust"] categories = ["command-line-utilities"]
[dependencies] clap = { version = "4.0.29", features = ["derive"] } file-size = "1.0.3" walkdir = "2.3.2" ```