Rust文件清单生成库simple-file-manifest的使用,高效生成和管理文件目录结构的工具

simple-file-manifest

这个crate提供了一个存储无关的接口,用于表示文件集合。它允许您构建文件列表,这些文件由路径名和内容+元数据组成。内容可以由引用的文件支持或在内存中定义。

元数据

pkg:cargo/simple-file-manifest@0.11.0 近3年前 2021版本 MIT OR Apache-2.0 11.7 KiB

安装

在您的项目目录中运行以下Cargo命令: cargo add simple-file-manifest

或者将以下行添加到您的Cargo.toml中: simple-file-manifest = “0.11.0”

文档 docs.rs/simple-file-manifest/0.11.0

代码仓库 github.com/indygreg/simple-file-manifest-rs

所有者 Gregory Szorc

内容中提供的示例:

use simple_file_manifest::FileManifest;
use std::path::Path;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 创建一个新的文件清单
    let mut manifest = FileManifest::default();
    
    // 添加内存中的文件内容
    manifest.add_file(
        "README.md", // 文件名
        "This is a sample readme file".as_bytes(), // 文件内容
    )?;
    
    // 添加来自文件系统的文件
    manifest.add_file_from_path(
        "src/main.rs", // 在清单中的路径
        Path::new("src/main.rs"), // 实际文件路径
    )?;
    
    // 迭代清单中的所有文件
    for entry in manifest.iter() {
        println!("File: {}", entry.path());
        println!("Size: {} bytes", entry.data().len());
    }
    
    // 将清单写入tar归档文件
    let mut tar_data = Vec::new();
    manifest.write_tar(&mut tar_data)?;
    
    println!("Generated tar archive with {} bytes", tar_data.len());
    
    Ok(())
}

完整示例demo:

use simple_file_manifest::FileManifest;
use std::path::Path;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 创建一个新的文件清单
    let mut manifest = FileManifest::default();
    
    // 添加内存中的文件内容
    manifest.add_file(
        "README.md", // 文件名
        "This is a sample readme file".as_bytes(), // 文件内容
    )?;
    
    // 添加来自文件系统的文件
    manifest.add_file_from_path(
        "src/main.rs", // 在清单中的路径
        Path::new("src/main.rs"), // 实际文件路径
    )?;
    
    // 迭代清单中的所有文件
    for entry in manifest.iter() {
        println!("File: {}", entry.path());
        println!("Size: {} bytes", entry.data().len());
    }
    
    // 将清单写入tar归档文件
    let mut tar_data = Vec::new();
    manifest.write_tar(&mut tar_data)?;
    
    println!("Generated tar archive with {} bytes", tar_data.len());
    
    Ok(())
}

1 回复

simple-file-manifest:高效生成和管理文件目录结构的Rust库

概述

simple-file-manifest是一个轻量级的Rust库,专门用于生成和管理文件目录清单。它能够递归扫描指定目录,生成包含文件路径、大小、修改时间等元数据的结构化清单,支持多种输出格式。

主要特性

  • 递归目录扫描
  • 支持JSON、TOML、YAML等多种输出格式
  • 可配置的元数据包含选项
  • 排除特定文件或目录
  • 计算文件哈希值(可选)

安装方法

在Cargo.toml中添加依赖:

[dependencies]
simple-file-manifest = "0.2"

基本用法

生成目录清单

use simple_file_manifest::FileManifest;

fn main() -> std::io::Result<()> {
    let manifest = FileManifest::new("./src")?
        .generate()?;
    
    println!("{}", manifest.to_json_pretty()?);
    Ok(())
}

配置选项示例

use simple_file_manifest::{FileManifest, ManifestConfig};

fn main() -> std::io::Result<()> {
    let config = ManifestConfig {
        include_file_size: true,
        include_modified_time: true,
        include_hash: true,
        exclude_patterns: vec!["*.tmp".to_string(), "temp/".to_string()],
        ..Default::default()
    };

    let manifest = FileManifest::with_config("./project", config)?
        .generate()?;
    
    // 保存为JSON文件
    manifest.to_json_file("manifest.json")?;
    
    Ok(())
}

读取和使用清单

use simple_file_manifest::FileManifest;

fn load_and_use_manifest() -> std::io::Result<()> {
    let manifest = FileManifest::from_json_file("manifest.json")?;
    
    for entry in manifest.entries() {
        println!("文件: {}, 大小: {} bytes", 
                 entry.path().display(), 
                 entry.size().unwrap_or(0));
    }
    
    Ok(())
}

高级用法

自定义筛选器

use simple_file_manifest::{FileManifest, FileEntry};

fn custom_filter() -> std::io::Result<()> {
    let manifest = FileManifest::new("./src")?
        .generate_with_filter(|entry: &FileEntry| {
            // 只包含Rust源文件且大于1KB的文件
            entry.path().extension().map(|ext| ext == "rs").unwrap_or(false)
                && entry.size().unwrap_or(0) > 1024
        })?;
    
    println!("筛选后的文件数量: {}", manifest.entries().len());
    Ok(())
}

比较两个清单

use simple_file_manifest::{FileManifest, ManifestDiff};

fn compare_manifests() -> std::io::Result<()> {
    let old_manifest = FileManifest::from_json_file("old_manifest.json")?;
    let new_manifest = FileManifest::from_json_file("new_manifest.json")?;
    
    let diff = ManifestDiff::compare(&old_manifest, &new_manifest);
    
    println!("新增文件: {:?}", diff.added_files());
    println!("删除文件: {:?}", diff.removed_files());
    println!("修改文件: {:?}", diff.modified_files());
    
    Ok(())
}

错误处理

use simple_file_manifest::FileManifest;

fn handle_errors() -> Result<(), Box<dyn std::error::Error>> {
    match FileManifest::new("/nonexistent/path") {
        Ok(manifest) => {
            let result = manifest.generate()?;
            println!("成功生成清单: {}个文件", result.entries().len());
        }
        Err(e) => eprintln!("错误: {}", e),
    }
    Ok(())
}

性能提示

  • 对于大型目录,考虑使用异步版本
  • 启用include_hash会显著影响性能,仅在需要时使用
  • 使用排除模式减少不必要的文件处理

这个库特别适合用于备份验证、文件同步、变更检测等场景,提供了简单易用的API来处理文件目录结构。

完整示例demo

// 完整示例:使用simple-file-manifest库生成、保存、读取和比较文件清单
use simple_file_manifest::{FileManifest, ManifestConfig, FileEntry, ManifestDiff};
use std::io::Result;

fn main() -> Result<()> {
    // 示例1:基本用法 - 生成目录清单并输出JSON
    println!("=== 基本用法示例 ===");
    let manifest = FileManifest::new("./src")?
        .generate()?;
    
    println!("生成的JSON清单:");
    println!("{}", manifest.to_json_pretty()?);
    
    // 示例2:配置选项 - 包含更多元数据并排除特定文件
    println!("\n=== 配置选项示例 ===");
    let config = ManifestConfig {
        include_file_size: true,
        include_modified_time: true,
        include_hash: true, // 注意:启用哈希计算会影响性能
        exclude_patterns: vec!["*.tmp".to_string(), "target/".to_string()],
        ..Default::default()
    };

    let detailed_manifest = FileManifest::with_config(".", config)?
        .generate()?;
    
    // 保存为JSON文件
    detailed_manifest.to_json_file("detailed_manifest.json")?;
    println!("详细清单已保存到 detailed_manifest.json");
    
    // 示例3:读取和使用清单文件
    println!("\n=== 读取清单示例 ===");
    let loaded_manifest = FileManifest::from_json_file("detailed_manifest.json")?;
    
    println!("清单中包含的文件:");
    for entry in loaded_manifest.entries() {
        println!("- {} ({} bytes)", 
                entry.path().display(), 
                entry.size().unwrap_or(0));
    }
    
    // 示例4:自定义筛选器 - 只处理特定文件
    println!("\n=== 自定义筛选器示例 ===");
    let filtered_manifest = FileManifest::new(".")?
        .generate_with_filter(|entry: &FileEntry| {
            // 只包含Rust文件且小于100KB的文件
            entry.path().extension().map(|ext| ext == "rs").unwrap_or(false)
                && entry.size().unwrap_or(0) < 100 * 1024
        })?;
    
    println!("筛选后的Rust文件数量: {}", filtered_manifest.entries().len());
    
    // 示例5:比较两个清单(模拟场景)
    println!("\n=== 清单比较示例 ===");
    // 假设我们有两个不同时间点的清单
    let old_files = detailed_manifest;
    let new_files = filtered_manifest;
    
    let diff = ManifestDiff::compare(&old_files, &new_files);
    
    println!("比较结果:");
    println!("新增文件: {:?}", diff.added_files().len());
    println!("删除文件: {:?}", diff.removed_files().len());
    println!("修改文件: {:?}", diff.modified_files().len());
    
    // 示例6:错误处理
    println!("\n=== 错误处理示例 ===");
    match FileManifest::new("/不存在的路径") {
        Ok(manifest) => {
            let result = manifest.generate()?;
            println!("成功生成清单: {}个文件", result.entries().len());
        }
        Err(e) => println!("预期中的错误: {}", e),
    }
    
    Ok(())
}

// 异步版本示例(需要启用异步特性)
#[cfg(feature = "async")]
async fn async_example() -> Result<()> {
    use simple_file_manifest::AsyncFileManifest;
    
    let manifest = AsyncFileManifest::new("./large_directory").await?
        .generate().await?;
    
    println!("异步生成的清单: {}个文件", manifest.entries().len());
    Ok(())
}

这个完整示例展示了simple-file-manifest库的主要功能:

  1. 基本目录扫描和JSON输出
  2. 配置元数据选项和排除模式
  3. 从文件读取清单数据
  4. 使用自定义筛选器处理特定文件
  5. 比较两个文件清单的差异
  6. 错误处理的最佳实践
  7. 异步用法的示例(需要启用异步特性)

使用时请确保在Cargo.toml中添加了正确的依赖,并根据实际需求调整配置参数。

回到顶部