Concurrent File Deduplicator using Ruby Threads
Build a Ruby command-line tool that finds duplicate files in large folders, using several threads to hash files at the same time. It groups files by size first, then compares SHA-256 hashes (with Ruby's Digest library) to find true duplicates, and reports how much space they waste. It can delete extra copies, but only when you explicitly ask, and it always keeps one. Finally, you'll measure how much the threads actually help, and learn why: Ruby's Global VM Lock (GVL) means threads speed up waiting on disk but not pure computation. You'll learn Ruby threads, Queue, Mutex, thread pools, streaming file hashing, and honest benchmarking.
- Estimate
- ~11.5h
- Steps
- 7
- Completed by
- 0
- Proposed by
- codeseed.app
Digest
Project roadmap
- 01
Set up the CLI
~1hCreate a Ruby project with a Gemfile and bin/dedupe. Parse options with OptionParser: a directory (required), --threads N (default: the number of CPU cores from Etc.nprocessors), --delete and --yes, and --json. Print usage and exit with code 2 for a missing or invalid directory. Done when: bin/dedupe --help prints the options.
- 02
Walk the folder and group by size
~1.5hCollect every regular file under the directory with Find.find, skipping symlinks and empty files, and recording each file's size. Group files by size with group_by and keep only sizes that appear more than once, since a file with a unique size can't have a duplicate. Print how many files were found and how many need hashing. Done when: the counts are correct for a test folder.
- 03
Hash files with a thread pool
~2.5hPut the files to hash into a Queue and start N worker threads. Each worker takes a path, computes its SHA-256 by reading the file in 1 MB chunks with Digest::SHA256 (so large files never load fully into memory), and stores the result in a shared hash protected by a Mutex. Report unreadable files instead of crashing. Done when: the hashes match the output of sha256sum for test files.
- 04
Report duplicates
~1.5hGroup paths by hash; each hash with more than one path is a duplicate group. Print the groups sorted by wasted space (size × (copies − 1)), largest first, then the total reclaimable space in human-readable units (KB, MB, GB). With --json, print the same data as JSON. Done when: a test folder with known duplicates reports exactly the expected groups.
- 05
Delete extra copies safely
~1.5hWith --delete, keep the oldest file in each group (by modification time) and list what would be deleted. Delete the files only when --yes is also given. Print what was deleted and how much space was freed. Never delete the last copy, and report any file that fails to delete. Done when: --delete alone deletes nothing, and --delete --yes removes exactly the extra copies.
- 06
Benchmark and explain
~2hCreate a large test folder (for example 2,000 files of various sizes), then time the hashing with 1, 2, 4 and 8 threads using Benchmark.realtime, running each several times. Write the results and your explanation in BENCHMARK.md: where threads helped, where they didn't, and how the GVL and disk caching affected the numbers. Done when: BENCHMARK.md has a results table and an explanation.
- 07
Write tests
~1.5hWrite minitest or RSpec tests that create temporary folders with duplicates, same-size files with different content, empty files and nested folders. Test grouping, hashing, the order of deleted files, and that no deletion happens without --yes. Done when: the tests pass.
Resources
Ready to build this?
Get a GitHub repo and start building. Your AI reviewer checks each step as you go.
Tech stack