2021-11-25 23:21:26 +00:00
|
|
|
use std::fs::DirEntry;
|
2021-11-25 22:39:16 +00:00
|
|
|
use std::io;
|
|
|
|
use std::path::PathBuf;
|
|
|
|
|
|
|
|
fn home_dir() -> PathBuf {
|
2021-11-25 23:28:31 +00:00
|
|
|
dirs::home_dir().expect("Couldn't find home dir")
|
2021-11-25 22:39:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn downloads_dir() -> PathBuf {
|
2021-11-26 00:35:24 +00:00
|
|
|
dirs::download_dir().expect("Couldn't find downloads dir")
|
|
|
|
}
|
|
|
|
|
|
|
|
fn pictures_dir() -> PathBuf {
|
|
|
|
dirs::picture_dir().expect("Couldn't find pictures dir")
|
2021-11-25 22:39:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn strip_null_bytes(str: &str) -> String {
|
|
|
|
str.replace('\0', "")
|
|
|
|
}
|
|
|
|
|
|
|
|
/// e.g. for ~/Music/ABBA/ABBA Gold:
|
|
|
|
/// `create_dir_if_not_exists(vec!["Music", "ABBA", "ABBA Gold"])`
|
|
|
|
fn create_dir_if_not_exists(path: Vec<&str>) -> PathBuf {
|
|
|
|
let mut dir = home_dir();
|
|
|
|
|
|
|
|
for item in path {
|
|
|
|
dir.push(item);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::fs::create_dir_all(&dir).unwrap_or(());
|
|
|
|
|
|
|
|
dir
|
|
|
|
}
|
|
|
|
|
|
|
|
fn move_file(file: PathBuf, mut destination: PathBuf) {
|
2022-01-04 17:59:16 +00:00
|
|
|
let file_name = file.file_name().expect("No file name").to_str().unwrap();
|
2021-11-25 22:39:16 +00:00
|
|
|
|
2022-01-04 17:59:16 +00:00
|
|
|
println!("Moving {:?} to {:?}", file_name, destination);
|
|
|
|
|
|
|
|
destination.push(file_name);
|
2021-11-25 22:39:16 +00:00
|
|
|
|
2022-06-27 22:00:08 +00:00
|
|
|
match fs_extra::file::move_file(file, destination, &Default::default()) {
|
|
|
|
Ok(_) => println!("OK!"),
|
|
|
|
Err(e) => println!("Couldn't move file: {:?}", e),
|
|
|
|
}
|
2021-11-25 22:39:16 +00:00
|
|
|
}
|
|
|
|
|
2021-11-25 23:21:26 +00:00
|
|
|
fn yes() -> bool {
|
|
|
|
let mut answer = String::new();
|
|
|
|
|
|
|
|
io::stdin().read_line(&mut answer)
|
|
|
|
.expect("Failed to read input");
|
|
|
|
|
|
|
|
answer.to_lowercase().starts_with("y")
|
|
|
|
}
|
|
|
|
|
2021-11-26 00:35:24 +00:00
|
|
|
fn handle_image(file: DirEntry) {
|
|
|
|
move_file(file.path(), pictures_dir());
|
|
|
|
}
|
|
|
|
|
|
|
|
fn handle_gif(file: DirEntry) {
|
|
|
|
let mut dir = pictures_dir();
|
|
|
|
|
|
|
|
dir.push("Internet");
|
|
|
|
dir.push("GIFs");
|
|
|
|
|
|
|
|
move_file(file.path(), dir);
|
|
|
|
}
|
|
|
|
|
2021-11-25 23:21:26 +00:00
|
|
|
fn handle_mp3(file: DirEntry) {
|
2022-01-04 17:59:16 +00:00
|
|
|
let meta = mp3_metadata::read_from_file(file.path());
|
|
|
|
|
|
|
|
if meta.is_err() {
|
|
|
|
println!("Couldn't read ID3 metadata for file {:?}", file.path());
|
|
|
|
}
|
2021-11-25 23:21:26 +00:00
|
|
|
|
2022-01-04 17:59:16 +00:00
|
|
|
if let Some(tag) = meta.unwrap().tag {
|
2021-11-25 23:21:26 +00:00
|
|
|
println!("----------------------");
|
|
|
|
println!("artist: {}", tag.artist.trim());
|
|
|
|
println!("album: {}", tag.album.trim());
|
|
|
|
println!("title: {}", tag.title.trim());
|
|
|
|
|
|
|
|
println!("move to: ~/Music/{}/{}/?", tag.artist.trim(), tag.album.trim());
|
|
|
|
|
|
|
|
if yes() {
|
|
|
|
move_file(
|
|
|
|
file.path(),
|
|
|
|
create_dir_if_not_exists(
|
|
|
|
vec![
|
|
|
|
"Music",
|
|
|
|
strip_null_bytes(&tag.artist).trim(),
|
|
|
|
strip_null_bytes(&tag.album).trim()
|
|
|
|
]
|
|
|
|
)
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
println!("skipping...");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-06 22:51:47 +00:00
|
|
|
fn handle_video(file: DirEntry) {
|
|
|
|
// todo if filename contains something like "(1971)" or "[2003]" it's a movie
|
|
|
|
// todo if filename contains something like "S03E21" it's a TV programme
|
|
|
|
move_file(file.path(), create_dir_if_not_exists(vec!["Videos"]));
|
|
|
|
}
|
|
|
|
|
2021-11-25 23:21:26 +00:00
|
|
|
fn handle_dir(path: PathBuf) {
|
|
|
|
let dir = std::fs::read_dir(path).expect("Couldn't read dir");
|
|
|
|
|
|
|
|
for inode in dir {
|
2022-01-04 17:59:16 +00:00
|
|
|
let inode = inode.expect("Couldn't read inode");
|
2021-11-25 22:39:16 +00:00
|
|
|
|
2022-06-27 22:03:49 +00:00
|
|
|
// recursively handle directories
|
2021-11-25 23:21:26 +00:00
|
|
|
if inode.metadata().unwrap().is_dir() {
|
|
|
|
handle_dir(inode.path());
|
|
|
|
}
|
2021-11-25 22:39:16 +00:00
|
|
|
|
2022-01-04 17:59:16 +00:00
|
|
|
if let Some(extension) = inode.path().extension().unwrap_or("none".as_ref()).to_str() {
|
|
|
|
match extension.to_string().to_lowercase().as_ref() {
|
|
|
|
"gif" => { handle_gif( inode) }
|
|
|
|
"jpg" => { handle_image(inode) }
|
|
|
|
"jpeg" => { handle_image(inode) }
|
|
|
|
"png" => { handle_image(inode) }
|
|
|
|
"mp3" => { handle_mp3( inode) }
|
2022-11-06 22:51:47 +00:00
|
|
|
"mp4" => { handle_video( inode) }
|
2022-01-04 17:59:16 +00:00
|
|
|
// todo m4a, flac, etc?
|
|
|
|
_ => { /*println!("Here's where we would do nothing.");*/ }
|
|
|
|
}
|
2021-11-25 23:21:26 +00:00
|
|
|
}
|
2021-11-25 22:39:16 +00:00
|
|
|
}
|
|
|
|
}
|
2021-11-25 23:21:26 +00:00
|
|
|
|
|
|
|
fn main() {
|
|
|
|
handle_dir(downloads_dir());
|
|
|
|
}
|