summaryrefslogtreecommitdiff
path: root/src/main.rs
diff options
context:
space:
mode:
authorNathan Reiner <nathan@nathanreiner.xyz>2024-03-30 00:00:44 +0100
committerNathan Reiner <nathan@nathanreiner.xyz>2024-03-30 00:00:44 +0100
commitf75555508819b02df06fb79c20d7ad23be8ecda6 (patch)
tree1b114533ce81bb61be4100bf356f132ddde05429 /src/main.rs
init commit
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs62
1 files changed, 62 insertions, 0 deletions
diff --git a/src/main.rs b/src/main.rs
new file mode 100644
index 0000000..12c920d
--- /dev/null
+++ b/src/main.rs
@@ -0,0 +1,62 @@
+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<String> = std::env::args().collect();
+
+ if args.len() != 3 {
+ println!("{} <source> <destination>", 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(())
+}