use std::path::Path; use anyhow::Result; use kdam::tqdm; use walkdir::WalkDir; async fn copy(from: String, to: String) -> std::io::Result<()> { let from_path = std::path::Path::new(&from); let to_path = std::path::Path::new(&to); if from_path.is_dir() { std::fs::create_dir_all(to)?; } else if from_path.is_file() { std::fs::create_dir_all(to_path.parent().unwrap())?; std::fs::copy(from, to)?; } Ok(()) } #[tokio::main] async fn main() -> Result<()> { let args: Vec = std::env::args().collect(); if args.len() != 3 { println!("{} ", args.first().unwrap()); return Ok(()); } let source = Path::new(&args[1]); let destination = Path::new(&args[2]); const MAX: usize = 100; let mut tasks = Vec::new(); let count = WalkDir::new(source) .into_iter() .filter_map(|e| e.ok()) .filter(|e| e.file_type().is_file()).count(); for entry in tqdm!(WalkDir::new(source) .into_iter() .filter_map(|e| e.ok()) .filter(|e| e.file_type().is_file()), total = count) { let from = entry.path().to_str().unwrap().to_string(); let rel = entry.path().strip_prefix(source)?; let to = { let mut target = destination.to_path_buf(); target.push(rel); target.to_str().unwrap().to_string() }; tasks.push(tokio::spawn(copy(from, to))); if tasks.len() > MAX { for task in tasks { task.await.unwrap()? } tasks = Vec::new(); } } Ok(()) }