use pathdiff::diff_paths; use sha2::{Digest, Sha256}; use std::fs::File; use std::io::Read; use std::path::{Path, PathBuf}; fn get_hash(fname: &str) -> Vec { let result1 = File::open(fname); if result1.is_err() { return vec![]; } let mut result = result1.unwrap(); let mut hasher = Sha256::new(); loop { let mut bif = [0; 1024]; let ur = result.read(&mut bif); if ur.is_err() { return vec![]; } hasher.update(&bif); if ur.unwrap() < 1024 { break; } } hasher.finalize().to_vec() } fn find_files(path: &Path) -> Vec { let mut ret = vec![]; let fss = std::fs::read_dir(path).unwrap(); for fs in fss { let fs = fs.unwrap(); if fs.file_type().unwrap().is_file() { ret.push(fs.path()); } else if fs.file_type().unwrap().is_dir() { let mut p = PathBuf::from(path); p.push(fs.file_name().to_str().unwrap()); ret.extend(find_files(p.as_path())); } } ret } fn linkdup(path: &Path) { let mut fhtable = vec![]; for z in find_files(path) { let pth = z; let hsh = get_hash(pth.to_str().unwrap()); fhtable.push((pth.to_str().unwrap().to_string(), hsh)); } fhtable.sort_by(|x, y| Ord::cmp(&x.0, &y.0)); let mut fable: Vec<(String, Vec)> = vec![]; for f in fhtable { let prstr = fable .iter() .filter_map(|x| if x.1 == f.1 { Some(x.0.clone()) } else { None }) .next(); if prstr.is_some() { // let f2m = std::fs::metadata(f.0.clone()).unwrap(); std::fs::remove_file(f.0.clone()).unwrap(); let mut zz = PathBuf::from(f.0.clone()); zz.pop(); std::os::unix::fs::symlink(diff_paths(prstr.unwrap(), zz).unwrap(), f.0.clone()) .unwrap(); } else { fable.push(f); } } } fn main() { linkdup(PathBuf::from(".").as_path()); }