1 个不稳定版本
0.1.0 | 2022年12月16日 |
---|
#2487 在 命令行工具
13KB
55 行
dirsearch
用法
$ dirsearch --number [num]
文章
大家好,我是@ekusiadadus。我在制作CLI工具。因为每次用Rust制作CLI工具都要重新配置环境很麻烦,所以我制作了一个模板。这次我将使用这个模板,用Rust快速制作一个简单的CLI工具。
模板在这里。https://github.com/ekusiadadus/rust-cli-template
这次要制作的命令行工具在这里。https://github.com/ekusiadadus/dirsearch
使用模板制作CLI工具
这次我们要快速制作一个常见的CLI工具,用于显示目录下文件夹和文件的数量和大小。
克隆模板
首先克隆模板。
git clone https://github.com/ekusiadadus/rust-cli-template.git
尝试用cargo run
执行看看
要使用模板,请移动到模板目录并执行cargo run
cd rust-cli-template
cargo run
如果一切顺利,将会执行名为rust-cli-template
的CLI工具。
到这一步,已经为使用cargo run
执行CLI工具而配置了环境。
(旁白) 使用mold + cargo watch
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
使用walkdir。
cargo add walkdir
要使用walkDir,请添加use walkdir::WalkDir;
。
获取目录下的文件和文件夹
use walkdir::WalkDir;
fn main() {
for entry in WalkDir::new(".") {
let entry = entry.unwrap();
println!("{}", entry.path().display());
}
}
执行cargo run
后,将显示目录下的文件和文件夹。
显示目录下文件和文件夹的数量和大小
我们将遍历目录下的文件和文件夹,显示文件的数量和大小。使用walkDir来遍历文件和文件夹非常简单。
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
。
(旁白 2) 在Rust中良好地显示文件大小...
在Rust中良好地显示文件大小可以使用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");
这是一个可以良好地显示文件大小的crate。
println!("{} files, {} bytes", count, fit_4(size));
使用它的样子。
嗯。
获取目录下文件的前N个
获取目录下文件的前N个。因为main
变得很长了,所以将其切分成函数。
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(())
}
执行后的样子。
获取目录下文件的前N个 (并行处理)
使用Clap将CLI工具化
使用 clap v4 将其转换为命令行工具。v4 与 v3 相比有相当大的不同,因此请边看 clap v4 的文档 边进行。
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();
}
实际运行时会有这样的感觉。
忘记使用 --number
参数会被责备。
例如,要显示前 100 项,请使用 --number 100
。
默认情况下,可以使用 Cargo.toml
中写入的信息,并通过 --help
显示。
在 Cargo.toml
中写入的信息将在 --help
中显示。
[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"]
# See more keys and their definitions at https://doc.rust-lang.net.cn/cargo/reference/manifest.html
[dependencies]
clap = { version = "4.0.29", features = ["derive"] }
file-size = "1.0.3"
walkdir = "2.3.2"
依赖关系
~1.3–9MB
~74K SLoC