I built a tool to recover deleted files from USB drives — here's what I learned about how 'delete' actually works
A while back I needed to pull deleted files off a USB stick — nothing dramatic, just a case where someone had wiped a drive and the files mattered. I went looking for tools and found the usual names: PhotoRec, TestDisk, The Sleuth Kit. All solid, all mature, all a bit much for what I actually wanted, which was something I could run from the command line, understand end to end, and extend myself.
So I built deep-recover.
The thing that actually surprised me
Before building this, I had the vague, half-correct idea most people have about "deleting" a file — you delete it, it's gone, maybe there's some spooky recovery magic involved. Building this tool forced me to actually understand what happens, and it's a lot more mundane than "spooky magic":
Deleting a file doesn't touch the data. It removes the pointer to the data — the directory entry, the index record — and marks those disk blocks as "free to reuse." The bytes just sit there, untouched, until the operating system happens to write something else into that same space.
That's it. That's the whole trick behind recovery. You're not un-deleting anything — you're reading data that was never actually erased, before something else overwrites it.
Once that clicked, the design of the tool became obvious: there are two completely different ways to go looking for that surviving data, and they fail in different situations, so I built both.
Two engines, because one isn't enough
Metadata recovery
Walks the filesystem's own bookkeeping (FAT directory entries, NTFS's MFT, ext4 inodes) using pytsk3, looking for entries still flagged deleted but whose data blocks are intact. When this works, you get the real filename, real size, and correct handling of fragmented files. This is "proper forensics."
Signature carving
Ignores the filesystem entirely and scans raw bytes for known file signatures — FF D8 FF for a JPEG, %PDF- for a PDF — reading forward until it hits an end marker or a safety cap. The fallback for when the filesystem index itself is gone.
deep-recover runs both by default and de-duplicates by content hash, so you get the best of whichever engine actually has something to offer for that particular drive.
The part I'm most careful about
I put that section right near the top of the README, not buried at the bottom, because a tool like this is genuinely dual-use. I wanted that boundary to be impossible to miss.
What I'd tell someone using it
A few things I learned the hard way while building and testing this, that aren't obvious until you hit them:
- Image the drive first, always. Never run recovery directly against a live device —
ddit to an image file, then rundeep-recoveragainst that. Working on a copy means you can't make things worse by accident. - SSDs are a different story than USB sticks. Modern SSDs run TRIM, which actually erases freed blocks at the hardware level shortly after deletion. Once that's happened, nothing gets the data back. The good news: most USB flash drives and SD cards don't implement TRIM, so recovery odds on the media people actually ask me about are much better than on an internal SSD.
- The less you use the drive after deleting, the better your odds, full stop. Every write is a chance to overwrite exactly the blocks you want back.
Why build this instead of just using PhotoRec
I want to be upfront: deep-recover isn't trying to replace TestDisk/PhotoRec or The Sleuth Kit — those are mature, battle-tested, and support more formats than I do right now. I built this because I wanted to actually understand the recovery process by implementing it, not just running someone else's binary — and because having a CLI tool I wrote myself means I can extend it fast when a specific case needs a signature format I don't have yet (adding a new type is a one-line addition to signatures.py).
That's really the throughline for a lot of what I build: not "this doesn't exist yet," but "I want to actually understand this well enough to have built it myself."
# install with the filesystem-metadata engine pip install deep-recover[metadata] # run it against a disk image, not a live device deep-recover usb_image.dd -o ./recovered
Try it yourself
MIT licensed, up on PyPI and GitHub. I'd genuinely welcome PRs — especially more file signatures for the carving engine.