What Happens When You Delete a File (Spoiler: Not Much)
The delete button lies, and understanding why has saved me more than once

Contents
I once spent an evening panicking over a deleted qcow2 disk image, then got most of it back with a tool that hadn’t been updated in a decade, because deleting a file on almost every filesystem in common use doesn’t do what the icon on the button suggests. It doesn’t shred the data. It doesn’t even touch most of it. It removes an entry from a directory listing and marks some space as reusable, and the actual bytes sit there, untouched, until something else happens to want that space. Understanding that gap between “deleted” and “gone” explains why recovery tools work, why secure deletion needs extra steps, and why a full disk sometimes behaves strangely even after you’ve cleared plenty of space.
The File Isn’t the Data, It’s a Pointer to the Data
Every mainstream filesystem — ext4, XFS, NTFS, APFS, even FAT — separates two things that look like one thing from the user’s side: the file’s content, sitting somewhere on the physical media as a collection of blocks, and the file’s metadata, a small record that says which blocks belong to it, how big it is, who owns it, and what it’s called. On Linux that metadata record is an inode; on NTFS it’s an MFT entry. The directory you see in a file manager is really just a table mapping names to these metadata records. When you open a file by name, the filesystem looks up the name in that table, follows it to the metadata record, and from there follows the block list to the actual content.
Deletion, in the overwhelming majority of cases, operates on the cheap end of that chain. The filesystem removes the directory entry — or in some implementations just marks it unused — and marks the inode and its blocks as free in a bitmap or free-space tree. That’s it. Two small bookkeeping updates, both fast, neither of which touches the actual content blocks. The reason this is the default behaviour isn’t laziness; it’s that actually erasing every block a large file occupies is proportional to the file’s size, while unlinking it is a fixed, tiny amount of work regardless of whether the file is one kilobyte or one terabyte. Filesystems are built for speed, and speed means doing as little as possible for an operation the user expects to be instant.
This is also why deleting a 200GB file takes the same fraction of a second as deleting a 200-byte one. If your filesystem genuinely zeroed content on delete, you’d see that difference immediately, and you don’t, because it isn’t happening.
Why Recovery Tools Can Bring Files Back
Because the blocks are marked free rather than cleared, the actual bytes remain exactly where they were, readable by anyone who bypasses the normal “look it up by name” path and instead scans the raw disk for recognisable structure. This is what tools like photorec, testdisk, and extundelete do: they read raw blocks directly, ignore the (now missing) directory entry, and look for patterns — a JPEG header, a PDF’s structure, an inode that still has a valid-looking block list even though nothing points to it any more — to reconstruct files without needing the filesystem’s own bookkeeping to cooperate.
| |
This works right up until something overwrites the freed blocks. Once new data lands on the same physical location, the old content is gone regardless of how good the recovery tool is, because there’s no shadow copy underneath — the bits are simply the bits, and new ones replace old ones permanently. This is the entire logic behind the classic advice to stop using a drive the moment you realise you deleted something important: every write, every temp file, every log rotation is another chance for the filesystem to hand out one of those freed blocks to something new, and the clock on recoverability starts the instant you hit delete, not hours later when you remember you needed the file.
SSDs complicate this story further. The TRIM command tells the drive’s controller which blocks are no longer in use so the drive can erase them ahead of time internally, which speeds up future writes but also means the content can be gone at the hardware level almost immediately after deletion, well before any application-level overwrite happens. On a spinning disk without TRIM, deleted content can survive for weeks. On an SSD with TRIM enabled, it might not survive the next few seconds. If you’ve ever wondered why undelete tools reliably work on old hard drives and reliably fail on modern SSDs, TRIM is most of the answer.
Why “Secure Delete” Is a Separate Feature
Because ordinary deletion leaves content readable, anything that actually needs to guarantee data is unrecoverable has to do real work: overwrite every block the file occupied, sometimes multiple times with different patterns, before releasing it. Tools like shred on Linux do exactly this.
| |
Notice the extra steps beyond overwriting: it also renames the file repeatedly before unlinking it, on the theory that the filename itself might leak something through filesystem journal entries or cached directory listings. That level of care is proportionate for a file that genuinely must not come back — key material, a database export with real customer data, anything you’d be embarrassed to explain if it turned up on a resold drive.
shred has one significant limitation worth knowing before you rely on it: on a copy-on-write or log-structured filesystem, or on any modern SSD doing wear levelling internally, “overwrite this exact block” isn’t a promise the tool can actually keep, because the underlying storage may quietly redirect writes to different physical cells rather than reusing the same ones. For genuinely sensitive data on modern SSDs, whole-disk encryption from the start — so that a deleted file’s plaintext was never on disk unencrypted to begin with — beats trying to shred after the fact. If you haven’t set that up, it’s worth reading about what a TLS handshake is actually saying as a companion piece on how encryption assumptions hold up under real threat models, even though that post is about data in transit rather than at rest.
Where This Actually Bites You
The gap between “deleted” and “gone” causes real, specific problems beyond the obvious privacy angle. A disk that reports plenty of free space can still throw “no space left on device” errors if a process holds a file handle open to something you deleted — the filesystem won’t actually free those blocks until the last handle closes, because releasing blocks a running process might still read from would corrupt its view of the file. This is an extremely common cause of “I deleted 40GB of logs and df still shows the disk full” tickets, and the fix is almost always finding the process still holding the handle, not deleting more files.
| |
That (deleted) marker in lsof output is the tell: the file is unlinked from every directory, invisible to ls, and still consuming exactly as much space as it did before, because a process is still writing to the inode directly. Restarting or signalling that process to reopen its log file is what actually reclaims the space; deleting things that are already gone from the directory listing achieves nothing.
Copy-on-Write Filesystems Change the Maths Again
Everything above describes the traditional ext4/NTFS model, where a file’s blocks are reused in place once freed. Filesystems like ZFS and Btrfs work differently, and it changes both the recovery story and the “why is my disk full” story in ways worth knowing before you rely on old assumptions on a newer box. Copy-on-write filesystems never overwrite a block that’s part of an existing snapshot; instead, a write creates a new block and updates pointers, leaving the old block alone until nothing — no file, no snapshot — references it any more. That means a deleted file on ZFS can be far more durably recoverable than on ext4, provided a snapshot from before the deletion still exists, because the snapshot holds its own reference to the old blocks regardless of what the live filesystem now points to.
The flip side is the free space confusion this causes for newcomers. Delete a large file on a ZFS dataset with hourly snapshots enabled, and df might barely move, because the blocks that file occupied are still referenced by last night’s snapshot and won’t actually free up until that snapshot itself expires and is destroyed. This is not a bug and not the filesystem “lying” about free space; it’s the direct, correct consequence of a snapshot doing its job. The practical lesson is to check zfs list -t snapshot before panicking about a delete that didn’t reclaim space — the space is spoken for by a snapshot, not lost, and it’ll return exactly when that snapshot’s retention window says it should.
| |
That USED column is the tell: it’s the space held exclusively by that snapshot, which is roughly what a delete since that point in time would return once the snapshot itself is gone. This is also, incidentally, why “I deleted the file, why do I still need a bigger disk” is a completely different conversation on a snapshotting filesystem than on ext4 — the honest answer is often “because you also want to keep being able to undo the delete,” which is the whole point of having snapshots in the first place.
Troubleshooting: When Deletion Doesn’t Free What You Expect
If space doesn’t come back after a delete, check for open file handles first with lsof +L1 before assuming the filesystem is lying to you — it almost never is. If a recovery is what you actually need, stop writing to the affected filesystem immediately, unmount it if you can, and work from a block-level image rather than the live disk, because every subsequent write is a chance to overwrite exactly the blocks you want back. If you’re trying to verify that a secure delete actually worked, don’t just trust the tool’s exit code; on anything backed by an SSD, assume wear levelling means some data may persist on cells the OS can no longer address directly, and treat full-disk encryption as the real control rather than after-the-fact overwriting.
Is It Worth Understanding This?
Yes, and not as trivia. It changes what you trust. It tells you that “empty the recycle bin” isn’t a security boundary, that a full disk error after a big cleanup means a process is holding a handle rather than the filesystem malfunctioning, and that if you actually need data gone — old credentials, a customer export, anything from a homelab box heading to resale — encryption from day one beats scrubbing after the fact. None of this required exotic tooling to understand, just following the pointer from name to inode to blocks and noticing how few of those steps deletion actually bothers with. If you found this useful, what a file actually is covers the inode side of this in more depth, and what RAID is not is the natural next read if “deleted things can come back” made you start thinking about “backed-up things can also not come back,” which is a different and arguably more important problem.




