From 9afcac846511579757e5ed96f04b22054e47391d Mon Sep 17 00:00:00 2001 From: Gabriel Kaszewski Date: Wed, 16 Jul 2025 00:49:16 +0200 Subject: [PATCH] init --- .gitignore | 1 + Cargo.lock | 25 ++++++++++++++++++++ Cargo.toml | 7 ++++++ src/main.rs | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 101 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..02fe179 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,25 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "cfg-if" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" + +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "restore-structure" +version = "0.1.0" +dependencies = [ + "encoding_rs", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..6080f84 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "restore-structure" +version = "0.1.0" +edition = "2024" + +[dependencies] +encoding_rs = "0.8.35" diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..9f883ab --- /dev/null +++ b/src/main.rs @@ -0,0 +1,68 @@ +use std::fs; +use std::io; +use std::path::{Path, PathBuf}; + +use encoding_rs::WINDOWS_1250; +#[cfg(unix)] +use std::os::unix::ffi::OsStrExt; + +fn main() -> io::Result<()> { + // Get input directory from command line arguments + let args: Vec = std::env::args().collect(); + if args.len() < 3 { + eprintln!("Usage: {} ", args[0]); + std::process::exit(1); + } + let input_dir = PathBuf::from(&args[1]); + let output_dir = PathBuf::from(&args[2]); + let input_dir = Path::new(&input_dir); + let output_dir = Path::new(&output_dir); + + fs::create_dir_all(output_dir)?; + + for entry in fs::read_dir(input_dir)? { + let entry = entry?; + let file_type = entry.file_type()?; + if !file_type.is_file() { + continue; + } + + // ---- Handle possibly non-UTF8 filenames ---- + #[cfg(unix)] + let file_name = { + let raw = entry.file_name(); + let bytes = raw.as_bytes(); + let (decoded, _, _) = WINDOWS_1250.decode(bytes); + decoded.into_owned() + }; + #[cfg(not(unix))] + let file_name = entry.file_name().to_string_lossy().into_owned(); + + let path_segments: Vec<&str> = file_name.split('\\').filter(|s| !s.is_empty()).collect(); + + let mut restored_path = output_dir.to_path_buf(); + for segment in path_segments { + restored_path.push(segment); + } + + if let Some(parent) = restored_path.parent() { + fs::create_dir_all(parent)?; + } + + // Try to move, fall back to copy+delete if needed (cross-filesystem safe) + match fs::rename(entry.path(), &restored_path) { + Ok(_) => {} + Err(_) => { + fs::copy(entry.path(), &restored_path)?; + // fs::remove_file(entry.path())?; + } + } + println!( + "Restored: {} -> {}", + entry.path().display(), + restored_path.display() + ); + } + + Ok(()) +}