Let’s build an environment for creating command line tools in Rust at blazing speed, 2022 edition.

Hi, @ekusiadadus here.
Are you creating CLI tools?
I’ve made a template for creating CLI tools in Rust, because it was a pain to set up the environment each time.
This time, I’ll use that template to make a simple CLI tool in Rust in a blazing fast way.
https://github.com/ekusiadadus/rust-cli-template
Here is the command line tool we will create.
https://github.com/ekusiadadus/dirsearch
CLI tools registered and distributed at https://crates.io/.
https://crates.io/crates/dirsearch
It can be installed with cargo install dirsearch.
Creating a CLI tool using templates
In this article, we will try to make a CLI tool that displays the number and size of folders and files that exist under common directories in a very fast way.
Cloning a Template
First, clone the temps.
git clone https://github.com/ekusiadadus/rust-cli-template.git
Try running it with cargo run
To use temps, go to the temps directory and run cargo run.
cd rust-cli-template cargo run
If all goes well, the CLI tool named rust-cli-template will be run like this.
At this stage, the environment is already ready to run the CLI tool with cargo run.
FYI Use mold + cargo watch
You do not have to use mold + cargo watch, but it is useful in the following ways
- hot reload
- fast build
I’ll post some reference articles around here if you’d like to use them.
moldを使うとRustのビルドが速くなる | κeenのHappy Hacκing Blog
moldとcargo watchを併用してより快適な開発環境を作る – Qiita
In this case, I used cargo watch -s ‘mold -run cargo run’ to create a hot reloadable environment.
Makefile is also included, so make watch will work.
After saving the file, it will automatically build and run.
Displaying the number and size of files and folders under a directory
Use walkDir to display the number and size of files and folders under a directory.
Install walkDir
cargo add walkdir
To use walkDir, add use walkdir::WalkDir;.
Obtain files and folders under a directory
use walkdir::WalkDir; fn main() { for entry in WalkDir::new(".") { let entry = entry.unwrap(); println!("{}", entry.path().display()); } }
When run with cargo run, files and folders under the directory are displayed.
Display the number and size of files and folders under a directory
To display the number and size of files and folders under a directory by traversing them.
Using walkdir, it is very easy to scan files and folders.
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); }
This is what it looks like when you actually run it with CARGO RUN.
We can see that there are 626 files under the current directory, with an overall size of 304742935 bytes.
(aside 2) To display the file size in a nice way in Rust…
To display the file size in a nice way in Rust, use file_size.
use file_size::fit_4; assert_eq!(&fit_4(999), "999"); assert_eq!(&fit_4(12345), "12K"); assert_eq!(&fit_4(999_999), "1.0M"); assert_eq!(&fit_4(7_155_456_789_012), "7.2T");
This is a crate that displays the file size in a nice way, like this.
println!("{} files, {} bytes", count, fit_4(size));
Here’s what it looks like when used.
Yeah, right.
Bring up the top N files under the directory
directory to bring in the top N files.
Also, main is getting too large, so we will cut it out into a function.
fn get_dir_size(dir: &str) -> Result<(), Box<dyn Error>> { let mut size: u64 = 0; let mut count: u64 = 0; let mut tops: Vec<Entry> = Vec::with_capacity(NUM + 1); let mut min_tops: u64 = 0; 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(()) }
When executed, it looks like this.
ディレクトリ配下のファイルで上位 N 件を持ってくる (並列処理)
Use Clap to make it a command line tool
clap v4 is used to make it a command line tool. v4 is quite different from v3, so please refer to the clap v4 documentation as you proceed.
use clap::Parser; #[derive(Parser)] #[command(author, version, about, long_about = None)] // Read from `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(); }
When actually executed, it looks like this.
--If you forget the number argument, you will be offended.
例えば、上位 100 件を表示するには、--number 100
とします。
デフォルトで --help
が使えるようになっています。
Cargo.toml
に書いた情報が、--help
で表示されます。
[package] name = "dirsearch" version = "0.1.0" edition = "2021" license = "MIT OR Apache-2.0" description = "🌸 Rust CLI Template using clap v4 🌸" readme = "README.md" homepage = "https://github.com/ekusiadadus/dirsearch" repository = "https://github.com/ekusiadadus/dirsearch" keywords = ["cli", "Japan", "Rust"] categories = ["command-line-utilities"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] clap = { version = "4.0.29", features = ["derive"] } file-size = "1.0.3" walkdir = "2.3.2"
dirsearch を cretes.io に登録して配布する
Now that we have the command line tool, we register it with https://crates.io/ so that we can actually cargo install dirsearch.
Prepare for release with cargo release –dry-run.
If successful, let’s actually install and run it locally.
cargo install –path . You can install locally with –path .
With dirsearch, you can use the command line tool.
Confirm that each command actually works.
It seems to be working properly.
It is actually working and will be distributed.
We have confirmed that the registration was successful.
Now I can cargo install dirsearch from anywhere!
summary
Let’s build an environment for creating command line tools in Rust at blazing speeds, 2022 edition, so how was it?
https://crates.io/crates/dirsearch
テンプレを使ってを配布するまでに 1 時間かからず行えました!
GitHub – ekusiadadus/dirsearch: This is a command line tool to search …
Above is the actual repository of the command line tool we distributed this time.
It’s so easy!
GitHub – ekusiadadus/rust-cli-template: A Private Template Repository …
他にも、Rust で作ったコマンドラインツールをテンプレから作っています。
仕事中にワールドカップをばれないように見るCLI ツールを Rust で作ってみた – Qiita
GitHub – ekusiadadus/samuraicup: A CLI tool to get World Cup 2022 twee…
This area is completely for my own use since I’m using the Twitter API, but it’s a lot of fun to make a command line tool in Rust!
The specs have changed quite a bit since clap v4, so it may be tough to get used to clap, but you can use templates to make it a blast, so please give it a try!