use std::fs::read_dir;
use std::path::Path;
use crypto::digest::Digest;
use crypto::md5::Md5;
pub fn md5(path: &Path) -> Result<String, std::io::Error> {
let mut m = Md5::new();
m.input(std::fs::read(path)?.as_slice());
Ok(m.result_str())
}
pub fn read_dir_(path: &Path, f: impl Fn(&Path) + Copy) -> Result<(), std::io::Error> {
let dir = read_dir(path)?;
for re in dir {
let file = re?;
if let Ok(filetype) = file.file_type() {
if filetype.is_dir() {
read_dir_(&file.path(), f)?;
} else {
f(&file.path());
}
}
}
Ok(())
}
#[cfg(test)]
#[test]
fn test_video_check() {
use std::cell::RefCell;
use std::collections::HashMap;
use crypto::digest::Digest;
use crypto::md5::Md5;
use std::io;
use std::cmp::max;
use std::thread;
use std::sync::{Arc, Mutex};
let path = std::path::Path::new("/mnt/视频");
let files = RefCell::new(HashMap::<u64, Vec<String>>::new());
read_dir_(&path, |p| {
let m = if let Ok(metadata) = p.metadata() {
metadata
} else {
return;
};
let mut file_map = files.borrow_mut();
if !file_map.contains_key(&m.len()) {
file_map.insert(m.len(), Vec::new());
file_map.get_mut(&m.len()).unwrap()
.push(String::from(p.to_str().unwrap()));
} else {
file_map.get_mut(&m.len()).unwrap()
.push(String::from(p.to_str().unwrap()));
}
}).unwrap();
let get_num = |info| -> usize {
println!("{}", info);
let mut s = String::new();
let stdin = io::stdin();
stdin.read_line(&mut s).unwrap();
s.pop();
s.parse().unwrap()
};
let mut delete_size: u64 = 0;
for (k, v) in files.borrow().iter() {
if v.len() > 1 {
let size = k.clone() as f64 / 1024i32.pow(2) as f64;
println!("len {:.02}MB: {:#?}", size, v);
let md5s = Arc::new(Mutex::new(Vec::<String>::new()));
let mut ths = vec![];
for i in 0..v.len() {
let md5_list = Arc::clone(&md5s);
let v_temp = v.clone();
ths.push(thread::spawn(move || {
let mut md5 = Md5::new();
md5.input(std::fs::read(Path::new(&v_temp[i])).unwrap().as_slice());
md5_list.lock().unwrap()
.push(md5.result_str());
println!("{}: Md5 {{{}}}", &v_temp[i], md5.result_str());
}));
}
for th in ths {
th.join().unwrap();
}
let mut md5s_temp = Arc::clone(&md5s).lock().unwrap().clone();
md5s_temp.dedup();
if md5s_temp.len() != 1 {
println!("EXISTS OUT OF ONE {:?} {{{:#?}}}", md5s_temp, v);
} else {
let mut templen = v[0].len();
let mut at: usize = 0;
let mut max_len = v[0].len();
for i in 1..v.len() {
if &v[i].len() < &templen {
templen = v[i].len();
at = i;
}
max_len = max(max_len, templen);
}
if max_len - v[at].len() > 1 {
for i in 0..v.len() {
println!("{}: {}", i, &v[i]);
}
let n = get_num("ENSURE SAVE: ");
if n < v.len() {
println!("SAVE '{}'", &v[n]);
at = n;
} else {
continue;
}
} else {
println!("SAVE '{}'", &v[at]);
}
for i in 0..v.len() {
if i != at {
println!("DELETE '{}'", &v[i]);
std::fs::remove_file(Path::new(&v[i])).unwrap();
delete_size += k.clone();
}
}
}
println!("\ndelete_size: {:.02}MB\n\n", delete_size as f64 / 1024i32.pow(2) as f64);
}
}
}