Simple tool for automatic file management
1use tokio::fs; 2use tokio::process::Command; 3 4use std::path::{Path, PathBuf}; 5 6/// Actions available for file 7#[derive(Clone, Debug, serde::Deserialize)] 8#[serde(rename_all = "snake_case")] 9pub enum Action { 10 /// Run given script with 1st argument. It will be ran in parent directory for given file 11 Script(Box<Path>), 12 /// Move given file to new destination 13 Move(Box<Path>), 14 /// Copy given file to new destination 15 Copy(Box<Path>), 16 /// Print message and do nothing 17 Echo(String), 18 /// Move to trash 19 Trash, 20} 21 22impl Action { 23 pub async fn run(self, source: PathBuf, execute: bool) { 24 if execute { 25 self.execute(source).await 26 } else { 27 self.dry_run(source).await 28 } 29 } 30 31 pub async fn dry_run(self, source: PathBuf) { 32 match self { 33 Action::Script(ref script) => println!("Execute {script:?} {source:?}"), 34 Action::Move(ref dest) => println!("Move {source:?} -> {dest:?}"), 35 Action::Copy(ref dest) => println!("Copy {source:?} -> {dest:?}"), 36 Action::Echo(ref message) => println!("{source:?} - {message}"), 37 Action::Trash => println!("Move {source:?} to trash"), 38 } 39 } 40 41 pub async fn execute(self, source: PathBuf) { 42 match self { 43 Action::Script(ref script) => { 44 Command::new(script.as_ref()) 45 .arg(&source) 46 .current_dir(source.parent().unwrap()) 47 .spawn() 48 .expect("Couldnt spawn process") 49 .wait() 50 .await 51 .expect("Child exited abnormally"); 52 } 53 54 Action::Copy(ref dest_dir) => { 55 let dest = crate::job::normalise_path(dest_dir).join(source.file_name().unwrap()); 56 fs::copy(&source, dest).await.expect("Couldnt copy file"); 57 } 58 59 Action::Move(ref dest_dir) => { 60 let dest = crate::job::normalise_path(dest_dir).join(source.file_name().unwrap()); 61 if let Err(err) = fs::rename(&source, &dest).await { 62 if err.raw_os_error() == Some(libc::EXDEV) { 63 panic!("X dev"); 64 } else { 65 panic!("Cannot move {source:?} -> {dest:?}: {err:?}"); 66 } 67 } 68 } 69 70 Action::Echo(ref message) => println!("{source:?} - {message}"), 71 72 Action::Trash => trash::delete(source).unwrap(), 73 } 74 } 75}