Compare commits
13 Commits
3eb674651b
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| f44272de79 | |||
| 8b0efc287a | |||
| 0be1ec6fca | |||
| 8c0d9a7236 | |||
| c311f3c2cb | |||
| e6b9b927f4 | |||
| 7c26c38ccb | |||
| 825482ba07 | |||
| 3c471c46b0 | |||
| ef110fcb94 | |||
| bb26036d19 | |||
| 12ddfd2b8c | |||
| 6e9e8df3bf |
125
Cargo.lock
generated
125
Cargo.lock
generated
@@ -2,6 +2,15 @@
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
@@ -16,31 +25,34 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "dirs"
|
||||
version = "4.0.0"
|
||||
version = "5.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059"
|
||||
checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225"
|
||||
dependencies = [
|
||||
"dirs-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs-sys"
|
||||
version = "0.3.6"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780"
|
||||
checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"option-ext",
|
||||
"redox_users",
|
||||
"winapi",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "download-organiser"
|
||||
version = "0.1.0"
|
||||
version = "0.1.2"
|
||||
dependencies = [
|
||||
"dirs",
|
||||
"fs_extra",
|
||||
"lazy_static",
|
||||
"mp3-metadata",
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -60,18 +72,36 @@ dependencies = [
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.108"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8521a1b57e76b1ec69af7599e75e38e7b7fad6610f037db8c79b127201b5d119"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||
|
||||
[[package]]
|
||||
name = "mp3-metadata"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eb969bc3573726b0bf60238d5d70f1aa6cc0f9e87f8db3e047b8309317319699"
|
||||
|
||||
[[package]]
|
||||
name = "option-ext"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.2.10"
|
||||
@@ -91,6 +121,23 @@ dependencies = [
|
||||
"redox_syscall",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.10.2+wasi-snapshot-preview1"
|
||||
@@ -98,23 +145,67 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
name = "windows-sys"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
name = "windows-targets"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
[package]
|
||||
name = "download-organiser"
|
||||
version = "0.1.0"
|
||||
version = "0.1.2"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
dirs = "^4.0.0"
|
||||
dirs = "^5.0.1"
|
||||
fs_extra = "^1.2.0"
|
||||
lazy_static = "^1.4.0"
|
||||
mp3-metadata = "^0.3.3"
|
||||
regex = "^1.6.0"
|
||||
|
||||
136
src/main.rs
136
src/main.rs
@@ -1,11 +1,18 @@
|
||||
use std::fs::DirEntry;
|
||||
use std::io;
|
||||
use std::{fs, io};
|
||||
use std::path::PathBuf;
|
||||
|
||||
use lazy_static::lazy_static;
|
||||
use regex::Regex;
|
||||
|
||||
fn home_dir() -> PathBuf {
|
||||
dirs::home_dir().expect("Couldn't find home dir")
|
||||
}
|
||||
|
||||
fn documents_dir() -> PathBuf {
|
||||
dirs::document_dir().expect("Couldn't find downloads dir")
|
||||
}
|
||||
|
||||
fn downloads_dir() -> PathBuf {
|
||||
dirs::download_dir().expect("Couldn't find downloads dir")
|
||||
}
|
||||
@@ -45,19 +52,36 @@ fn move_file(file: PathBuf, mut destination: PathBuf) {
|
||||
}
|
||||
}
|
||||
|
||||
fn yes() -> bool {
|
||||
fn user_input() -> String {
|
||||
let mut answer = String::new();
|
||||
|
||||
io::stdin().read_line(&mut answer)
|
||||
.expect("Failed to read input");
|
||||
|
||||
answer.to_lowercase().starts_with("y")
|
||||
answer
|
||||
}
|
||||
|
||||
// todo: add other input options e.g. "d" for delete, "a" for "yes to this whole album"
|
||||
fn yes() -> bool {
|
||||
user_input().to_lowercase().starts_with("y")
|
||||
}
|
||||
|
||||
fn handle_document(file: DirEntry) {
|
||||
move_file(file.path(), documents_dir());
|
||||
}
|
||||
|
||||
fn handle_image(file: DirEntry) {
|
||||
move_file(file.path(), pictures_dir());
|
||||
}
|
||||
|
||||
fn handle_iso(file: DirEntry) {
|
||||
let mut dir = home_dir();
|
||||
|
||||
dir.push("ISOs");
|
||||
|
||||
move_file(file.path(), dir);
|
||||
}
|
||||
|
||||
fn handle_gif(file: DirEntry) {
|
||||
let mut dir = pictures_dir();
|
||||
|
||||
@@ -72,15 +96,24 @@ fn handle_mp3(file: DirEntry) {
|
||||
|
||||
if meta.is_err() {
|
||||
println!("Couldn't read ID3 metadata for file {:?}", file.path());
|
||||
} else if let Some(tag) = meta.unwrap().tag {
|
||||
let mut artist = tag.artist.trim().to_string();
|
||||
let album = tag.album.trim();
|
||||
let title = tag.title.trim();
|
||||
|
||||
println!("----------------------");
|
||||
println!("file: {:?}", file.path());
|
||||
println!("artist: {}", artist);
|
||||
println!("album: {}", album);
|
||||
println!("title: {}", title);
|
||||
|
||||
if artist.len() == 0 {
|
||||
println!("Enter artist name?");
|
||||
artist = user_input();
|
||||
// is there a way to update mp3 metadata here?
|
||||
}
|
||||
|
||||
if let Some(tag) = meta.unwrap().tag {
|
||||
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());
|
||||
println!("move to: ~/Music/{}/{}/?", artist.clone(), album);
|
||||
|
||||
if yes() {
|
||||
move_file(
|
||||
@@ -99,9 +132,58 @@ fn handle_mp3(file: DirEntry) {
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_dir(path: PathBuf) {
|
||||
let dir = std::fs::read_dir(path).expect("Couldn't read dir");
|
||||
fn handle_pdf(file: DirEntry) {
|
||||
let mut dir = documents_dir();
|
||||
|
||||
dir.push("PDFs");
|
||||
|
||||
move_file(file.path(), dir);
|
||||
}
|
||||
|
||||
/// if filename contains something like `(1971)` or `[2003]` or `.1985.` it's a movie
|
||||
fn is_movie(file: &DirEntry) -> bool {
|
||||
lazy_static! {
|
||||
static ref MOVIE: Regex = Regex::new(r"\.\d{4}\.|\(\d{4}\)|\[\d{4}]").unwrap();
|
||||
}
|
||||
|
||||
MOVIE.is_match(file.file_name().to_str().unwrap())
|
||||
}
|
||||
|
||||
/// if filename contains something like "S03E21" it's a TV programme
|
||||
fn is_tv_episode(file: &DirEntry) -> bool {
|
||||
lazy_static! {
|
||||
static ref TV: Regex = Regex::new(r"[sS]\d{2}\s*[eE][pP]?\d{2}").unwrap();
|
||||
}
|
||||
|
||||
TV.is_match(file.file_name().to_str().unwrap())
|
||||
}
|
||||
|
||||
fn handle_video(file: DirEntry) {
|
||||
let mut destination = vec!["Videos"];
|
||||
|
||||
if is_tv_episode(&file) {
|
||||
destination.push("TV");
|
||||
} else if is_movie(&file) {
|
||||
// todo match decade?
|
||||
destination.push("Movies");
|
||||
}
|
||||
|
||||
println!(
|
||||
"Move to ~/{}/{}?", destination.join("/"), file.file_name().to_str().unwrap()
|
||||
);
|
||||
|
||||
if yes() {
|
||||
move_file(file.path(), create_dir_if_not_exists(destination));
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_dir(path: PathBuf) {
|
||||
let mut dir = std::fs::read_dir(&path).expect("Couldn't read dir");
|
||||
|
||||
if dir.next().is_none() {
|
||||
println!("Deleting empty dir: {:?}", path);
|
||||
fs::remove_dir(path).expect("Couldn't delete dir")
|
||||
} else {
|
||||
for inode in dir {
|
||||
let inode = inode.expect("Couldn't read inode");
|
||||
|
||||
@@ -112,13 +194,33 @@ fn handle_dir(path: PathBuf) {
|
||||
|
||||
if let Some(extension) = inode.path().extension().unwrap_or("none".as_ref()).to_str() {
|
||||
match extension.to_string().to_lowercase().as_ref() {
|
||||
"csv" => { handle_document(inode) }
|
||||
"doc" => { handle_document(inode) }
|
||||
"docx" => { handle_document(inode) }
|
||||
"odt" => { handle_document(inode) }
|
||||
"rtf" => { handle_document(inode) }
|
||||
"xls" => { handle_document(inode) }
|
||||
"xlsx" => { handle_document(inode) }
|
||||
"gif" => { handle_gif( inode) }
|
||||
"jpg" => { handle_image(inode) }
|
||||
"jpeg" => { handle_image(inode) }
|
||||
"png" => { handle_image(inode) }
|
||||
"jpg" => { handle_image( inode) }
|
||||
"jpeg" => { handle_image( inode) }
|
||||
"png" => { handle_image( inode) }
|
||||
"bin" => { handle_iso( inode) }
|
||||
"cue" => { handle_iso( inode) }
|
||||
"iso" => { handle_iso( inode) }
|
||||
"mp3" => { handle_mp3( inode) }
|
||||
// todo m4a, flac, etc?
|
||||
_ => { /*println!("Here's where we would do nothing.");*/ }
|
||||
"pdf" => { handle_pdf( inode) }
|
||||
"avi" => { handle_video( inode) }
|
||||
"m4v" => { handle_video( inode) }
|
||||
"mkv" => { handle_video( inode) }
|
||||
"mp4" => { handle_video( inode) }
|
||||
"srt" => { handle_video( inode) }
|
||||
"7z" => { }
|
||||
"parts" => { }
|
||||
"torrent" => { }
|
||||
"zip" => { }
|
||||
_ => { println!("Not sure what to do with file: {:?}.", inode.path()); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user