#日本 #cli-tool #cli #rust

应用 dirsearch

🌸 使用clap v4构建的Rust CLI模板 🌸

1 个不稳定版本

0.1.0 2022年12月16日

#2487命令行工具

MIT/Apache

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工具而配置了环境。

image.png

(旁白) 使用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运行。

保存时将自动构建并运行。

build-with-mold.gif

显示目录下文件和文件夹的数量和大小

使用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后,将显示目录下的文件和文件夹。

image.png

显示目录下文件和文件夹的数量和大小

我们将遍历目录下的文件和文件夹,显示文件的数量和大小。使用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后,将会是这样的。

image.png

当前目录下有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));

使用它的样子。

image.png

嗯。

获取目录下文件的前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(())
}

执行后的样子。

image.png

获取目录下文件的前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();
}

实际运行时会有这样的感觉。

image.png

忘记使用 --number 参数会被责备。

image.png

例如,要显示前 100 项,请使用 --number 100

image.png

默认情况下,可以使用 Cargo.toml 中写入的信息,并通过 --help 显示。

image.png

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