Deduplicator

Find, Sort, Filter & Delete duplicate files

## Usage ```bash find,filter and delete duplicate files Usage: deduplicator [OPTIONS] [scan_dir_path] Arguments: [scan_dir_path] Run Deduplicator on dir different from pwd (e.g., ~/Pictures ) Options: -T, --exclude-types Exclude Filetypes [default = none] -t, --types Filetypes to deduplicate [default = all] -i, --interactive Delete files interactively -m, --min-size Minimum filesize of duplicates to scan (e.g., 100B/1K/2M/3G/4T) [default: 1b] -D, --max-depth Max Depth to scan while looking for duplicates -d, --min-depth Min Depth to scan while looking for duplicates -f, --follow-links Follow links while scanning directories -s, --strict Guarantees that two files are duplicate (performs a full hash) -p, --progress Show Progress spinners & metrics -h, --help Print help -V, --version Print version ``` ### Examples ```bash # Scan for duplicates recursively from the current dir, only look for png, jpg & pdf file types & interactively delete files deduplicator -t pdf,jpg,png -i # Scan for duplicates recursively from current dir, exclude png and jpg file types deduplicator -T jpg,png # Scan for duplicates recursively from the ~/Pictures dir, only look for png, jpeg, jpg & pdf file types & interactively delete files deduplicator ~/Pictures/ -t png,jpeg,jpg,pdf -i # Scan for duplicates in the ~/Pictures without recursing into subdirectories deduplicator ~/Pictures --max-depth 0 # look for duplicates in the ~/.config directory while also recursing into symbolic link paths deduplicator ~/.config --follow-links # scan for duplicates that are greater than 100mb in the ~/Media directory deduplicator ~/Media --min-size 100mb ``` ## Demo ![record](https://github.com/user-attachments/assets/fcfdd9bf-4d05-41b6-a82e-367634eeaa73) ## Installation Currently, you can only install deduplicator using cargo package manager. ### Cargo > GxHash relies on aes hardware acceleration, so please set `RUSTFLAGS` to `"-C target-feature=+aes"` or `"-C target-cpu=native"` before > installing. #### install from crates.io ```bash $ RUSTFLAGS="-C target-cpu=native" cargo install deduplicator ``` #### install from git ```bash $ RUSTFLAGS="-C target-cpu=native" cargo install deduplicator --git https://github.com/sreedevk/deduplicator ``` ## Performance Deduplicator uses size comparison and [GxHash](https://docs.rs/gxhash/latest/gxhash/) to quickly check a large number of files to find duplicates. its also heavily parallelized. The default behavior of deduplicator is to only hash the first page (4K) of the file. This is to ensure that performance is the default priority. You can modify this behavior by using the `--strict` flag which will hash the whole file and ensure that 2 files are indeed duplicates. I'll add benchmarks in future versions. ### Benchmarks I've used hyperfine to run deduplicator on files generated by the rake file at `rakelib/benchmark.rake`. The Benchmarking accuracy can further be improved by isolating runs inside restricted docker containers. I'll include that in the future. For now, here's the hyperfine output on my i7-12800H laptop with 32G of RAM. #### Fewer Large Files ``` # hyperfine -N --warmup 80 './target/release/deduplicator bench_artifacts' Benchmark 1: ./target/release/deduplicator bench_artifacts Time (mean ± σ): 2.3 ms ± 0.5 ms [User: 2.4 ms, System: 4.6 ms] Range (min … max): 1.4 ms … 6.7 ms 1457 runs dust 'bench_artifacts' 40M ┌── file_0_fwds.bin │████ │ 2% 113M ├── file_1_fwds.bin │███████████ │ 5% 390M ├── file_0_fwdcbss.bin│█████████████████████████████████████ │ 16% 390M ├── file_0_fwscas.bin │█████████████████████████████████████ │ 16% 390M ├── file_0_fwss.bin │█████████████████████████████████████ │ 16% 390M ├── file_1_fwdcbss.bin│█████████████████████████████████████ │ 16% 390M ├── file_1_fwscas.bin │█████████████████████████████████████ │ 16% 390M ├── file_1_fwss.bin │█████████████████████████████████████ │ 16% 2.4G ┌─┴ bench_artifacts │██████████████████████████████████████████████████████████████████ │ 100% ``` #### Many Small Files ``` # hyperfine --warmup 20 './target/release/deduplicator bench_artifacts' Benchmark 1: ./target/release/deduplicator bench_artifacts Time (mean ± σ): 88.6 ms ± 10.3 ms [User: 275.3 ms, System: 232.7 ms] Range (min … max): 66.8 ms … 108.0 ms 41 runs dust 'bench_artifacts' 3.9M ┌── file_98_fwss.bin │█ │ 0% 3.9M ├── file_990_fwdcbss.bin│█ │ 0% 3.9M ├── file_990_fwscas.bin │█ │ 0% 3.9M ├── file_990_fwss.bin │█ │ 0% 3.9M ├── file_991_fwdcbss.bin│█ │ 0% 3.9M ├── file_991_fwscas.bin │█ │ 0% 3.9M ├── file_991_fwss.bin │█ │ 0% 3.9M ├── file_992_fwdcbss.bin│█ │ 0% 3.9M ├── file_992_fwscas.bin │█ │ 0% 3.9M ├── file_992_fwss.bin │█ │ 0% 3.9M ├── file_993_fwdcbss.bin│█ │ 0% 3.9M ├── file_993_fwscas.bin │█ │ 0% 3.9M ├── file_993_fwss.bin │█ │ 0% 3.9M ├── file_994_fwdcbss.bin│█ │ 0% 3.9M ├── file_994_fwscas.bin │█ │ 0% 3.9M ├── file_994_fwss.bin │█ │ 0% 3.9M ├── file_995_fwdcbss.bin│█ │ 0% 3.9M ├── file_995_fwscas.bin │█ │ 0% 3.9M ├── file_995_fwss.bin │█ │ 0% 3.9M ├── file_996_fwdcbss.bin│█ │ 0% 3.9M ├── file_996_fwscas.bin │█ │ 0% 3.9M ├── file_996_fwss.bin │█ │ 0% 3.9M ├── file_997_fwdcbss.bin│█ │ 0% 3.9M ├── file_997_fwscas.bin │█ │ 0% 3.9M ├── file_997_fwss.bin │█ │ 0% 3.9M ├── file_998_fwdcbss.bin│█ │ 0% 3.9M ├── file_998_fwscas.bin │█ │ 0% 3.9M ├── file_998_fwss.bin │█ │ 0% 3.9M ├── file_999_fwdcbss.bin│█ │ 0% 3.9M ├── file_999_fwscas.bin │█ │ 0% 3.9M ├── file_999_fwss.bin │█ │ 0% 3.9M ├── file_99_fwdcbss.bin │█ │ 0% 3.9M ├── file_99_fwscas.bin │█ │ 0% 3.9M ├── file_99_fwss.bin │█ │ 0% 3.9M ├── file_9_fwdcbss.bin │█ │ 0% 3.9M ├── file_9_fwscas.bin │█ │ 0% 3.9M ├── file_9_fwss.bin │█ │ 0% 11G ┌─┴ bench_artifacts │████████████████████████████████████████████████████████████████ │ 100% ``` ## proposed - [ ] parallelization - [ ] scanning + processing sw + processing hw + formatting + printing - [ ] max file path size should use the last set of duplicates - [ ] add more unit tests - [ ] test against different filesystems - [ ] test against different file name encodings - [ ] restore json output (was removed in 0.3 due to quality issues) - [ ] fix memory leak on very large filesystems - [ ] maybe use a bloom filter - [ ] reduce FileInfo size - [ ] output a duplicate tree - [ ] tui - [ ] change the default hashing method to include the first & last page of a file (8K) - [ ] provide option to localize duplicate detection to arbitrary levels relative to current directory - [ ] bulk operations - [ ] --keep-latest - [ ] --keep-oldest - [ ] --keep-last-modified - [ ] --keep-first-modified ## v0.3.1 - [x] parallelization - [x] (scanning + processing sw + processing hw) & formatting & printing - [ ] remove formatting step and write directly to stdout (tree mode) - [x] Increase the number of pages hashed in partial hashing ## v0.3.0 - [x] parallelization - [x] (scanning) + (processing sw & processing hw & formatting & printing) - [x] reduce cloning values on the heap - [x] add a partial hashing mode (--strict) - [x] add unit tests - [x] add silent mode - [x] update documentation - [x] remove color output - [x] progress bar improvements - [x] use progress bar groups - [x] remove broken json rendering - [x] add benchmarks