You deleted the wrong file. Maybe an rm -rf went one directory too far, a file manager emptied something you needed, or a disk started failing and took a folder with it. Take a breath: on GNU/Linux, deleting a file usually does not erase its contents. It removes the name that points at the data and marks the space as free — but the actual bytes sit on the disk untouched until something else writes over them. Recovery is a race against those new writes, and the moment you notice is the moment your odds are best.
This guide covers both ways back: the tool-free tricks built into every Linux system (open file handles, snapshots, the trash, grep on the raw disk) and the dedicated recovery tools for when those are not enough. Every tool here is free and open source — GPL or public domain, and a one-line apt/pacman/dnf away. Nothing on this page is paid, proprietary, or cloud.
You do not need to read it top to bottom. Jump to your situation with the table of contents, but read the next section first — it is the one rule that decides whether anything else will work.
The golden rule: stop writing to that disk now
Every byte written to the filesystem you are trying to recover from can land on top of the very data you want back. The single most important thing you can do is stop using that filesystem immediately.
Warning: do not save your recovery tools to the affected disk, do not browse the web (the cache writes), and never write recovered files back onto the same filesystem you are pulling them from. Recover onto a different disk — a second drive, a USB stick, or a network share.
If the lost file was on your system / root partition, the safest move is to stop the machine and boot from a live USB (any Linux installer ISO works), so the damaged filesystem is never mounted read-write. If it was on a separate data disk, just unmount it — or remount it read-only so nothing can touch it:
# Find the device and where it is mounted
lsblk -o NAME,SIZE,FSTYPE,MOUNTPOINTS
# Best: unmount it entirely
sudo umount /dev/sdX1
# If something is using it and you cannot unmount, force it read-only instead
sudo mount -o remount,ro /dev/sdX1
Throughout this guide, /dev/sdX1 is a stand-in for your partition. Confirm the real name with lsblk by its size and mount point before running anything — pointing a recovery command at the wrong disk is its own disaster.
Make a safe copy first (image the device)
The professional habit is to never work on the original at all. Instead you make a byte-for-byte image of the disk and do all recovery against the copy, so no tool — and no mistake — can ever make things worse. This is essential if the drive is failing (clicking, throwing read errors, dropping out).
The right tool is GNU ddrescue (free software, GPLv3; package gddrescue on Debian/Mint/Ubuntu, ddrescue on Arch/Manjaro/Fedora). Unlike plain dd, it keeps going past bad sectors, retries them later, and records a map file so you can resume:
# Install (Debian / Mint / Ubuntu)
sudo apt install gddrescue
# Install (Arch / Manjaro)
sudo pacman -S ddrescue
# Install (Fedora)
sudo dnf install ddrescue
# Clone the whole partition to an image file ON ANOTHER DISK.
# The third argument is a map/log file so you can stop and resume.
sudo ddrescue -d -r3 /dev/sdX1 /mnt/backup/rescue.img /mnt/backup/rescue.map
Tip: if the disk is perfectly healthy and you only want a quick image, plain
ddworks too:sudo dd if=/dev/sdX1 of=/mnt/backup/rescue.img bs=4M status=progress. But for anything flaky, reach forddrescue— it is built for exactly this.
From here on, wherever a command takes /dev/sdX1, you can usually hand it rescue.img instead and recover from the safe copy. The carving and filesystem tools below all accept an image file in place of a device.
Was it just the trash?
Before any heavy machinery: if you deleted the file from a desktop file manager (Files/Nautilus, Dolphin, Thunar…), it almost certainly went to the trash, not oblivion. The freedesktop standard keeps it under your home directory:
# the deleted files themselves
ls ~/.local/share/Trash/files/
# where each one came from
ls ~/.local/share/Trash/info/
Restore it from the file manager's Trash, or from the terminal with trash-cli (free software, GPLv2; it gives the command line the same safe trash the desktop uses):
# or pacman -S / dnf install trash-cli
sudo apt install trash-cli
# show what is in the trash
trash-list
# pick a file to put back
trash-restore
On a GNOME-based system the built-in gio command does the same without installing anything:
# show trashed items
gio trash --list
gio trash --restore trash:///myfile.txt
Tip: the command line's
rmdoes not use the trash — it unlinks immediately. Get in the habit of typingtrash put somefileinstead ofrm somefilefor anything you might regret, and this whole guide becomes a once-a-year event.
Deleted but still open: recover straight from /proc
Here is the most reliable recovery on the whole page, and it needs no special tool at all. If a running program still has the file open when you delete it — a log being written, a video playing, a database, a document in an editor — the data is not gone. Linux keeps the contents alive until the last open handle closes, and exposes that handle as a file under /proc.
Find the open-but-deleted files with lsof (free software, under a permissive Purdue/BSD-style license; usually already installed):
# list open files whose link count is 0 (deleted)
sudo lsof +L1
# or search by name:
sudo lsof | grep deleted
Note the PID (process id) and the FD (file-descriptor number) from the output, then copy the data back out of /proc/<pid>/fd/<fd>:
# Example: process 4123 has the deleted file open as descriptor 7
sudo cp /proc/4123/fd/7 /home/you/recovered-file
Warning: this only works while the program stays running. If you close the editor, stop the service, or reboot, the handle disappears and the data is freed. So recover first, ask questions later — do not restart anything.
Snapshots and backups: recover without undelete tools
If your system was set up with snapshots, recovery is trivial and total — you just copy the file out of a point-in-time view of the disk. This is by far the most dependable method, which is the real lesson: set it up before you need it (see the last section).
Btrfs (including Timeshift snapshots)
If your filesystem is Btrfs (the default on Fedora, openSUSE, and Manjaro, among others), snapshots are built in — and many systems take them automatically with Timeshift or Snapper (both free software, GPL). Start by listing what exists:
# show every subvolume and snapshot on the filesystem
sudo btrfs subvolume list /
On a typical Timeshift-on-Btrfs layout that prints something like the following. Your live system is the @ subvolume (mounted at /) plus @home (mounted at /home); each Timeshift snapshot is a frozen copy of @, named by date:
ID 256 gen 19355 top level 5 path @
ID 257 gen 19356 top level 5 path @home
ID 258 gen 19352 top level 5 path @cache
ID 259 gen 19354 top level 5 path @log
ID 267 gen 16595 top level 5 path timeshift-btrfs/snapshots/2026-06-15_22-53-08/@
ID 268 gen 16595 top level 5 path timeshift-btrfs/snapshots/2026-06-17_20-21-14/@
ID 269 gen 16596 top level 5 path timeshift-btrfs/snapshots/2026-06-18_22-43-41/@
Those snapshot paths are listed relative to the filesystem's top level, not relative to / — and since / is itself just the @ subvolume, you cannot reach them directly. To browse a snapshot, mount the top level (subvolid=5) somewhere temporary. First find your root device (this also resolves a LUKS-encrypted root to its unlocked name):
# store the device behind / in a variable: --nofsroot drops the [/@] suffix,
# and a variable keeps the long name from wrapping onto a second line later
DEV=$(findmnt -no SOURCE --nofsroot /)
# show it (e.g. /dev/sda2, or /dev/mapper/luks-... if encrypted)
echo "$DEV"
Warning: plain
findmnt -no SOURCE /prints something like/dev/sda2[/@]. That[/@]is the subvolume currently mounted there, not part of the device name — do not paste it into the mount command (your shell will also choke on the brackets). The--nofsrootabove drops it for you; otherwise use only the part before the[.
# mount the WHOLE filesystem (its top level) read-only, so browsing cannot change anything
sudo mkdir -p /mnt/btrfs-top
sudo mount -o ro,subvolid=5 "$DEV" /mnt/btrfs-top
# the snapshots are now visible as ordinary folders (use the absolute path!)
ls /mnt/btrfs-top/timeshift-btrfs/snapshots/
Warning: keep the
mountcommand on a single line, mount point included. If it gets split andmountsees the device but no mount point, it falls back to your/etc/fstabentry for/— which pinssubvol=/@— and fails withsubvol '/@' does not match subvolid 5. The"$DEV"variable above keeps the long device name from wrapping, which is what usually causes the split.
Tip: browse the mount by its absolute path —
ls /mnt/btrfs-top, not a barelsin whatever directory you happen to be in. A successful mount shows@,@home,@cache,@log, andtimeshift-btrfsthere.
Warning: do not
cdinto/mnt/btrfs-topbefore you mount it. A shell already sitting in the mount point keeps looking at the now-hidden empty directory underneath, solsstill showstotal 0even after the mount succeeds. If that happens, step out and back in to pick up the mount:cd / && cd /mnt/btrfs-top.
Inside a snapshot, the @ folder is what / looked like at that moment. So a live file at /etc/fstab sits at …/<snapshot>/@/etc/fstab — the rule is simply "put @ in front of the path". Browse to what you lost:
ls -l /mnt/btrfs-top/timeshift-btrfs/snapshots/2026-06-18_22-43-41/@/etc/
Recover a single file by copying it back out. The -a flag preserves its permissions, owner, and timestamps:
sudo cp -a /mnt/btrfs-top/timeshift-btrfs/snapshots/2026-06-18_22-43-41/@/etc/myapp.conf /etc/myapp.conf
Recover a whole directory the same way — --reflink=auto makes it an instant copy-on-write copy, since source and destination are one filesystem:
sudo cp -a --reflink=auto /mnt/btrfs-top/timeshift-btrfs/snapshots/2026-06-18_22-43-41/@/etc/myapp /etc/myapp
Or merge into an existing directory with rsync, previewing first (the trailing slashes mean "the contents of"):
# preview the changes without writing anything
sudo rsync -aAXv --dry-run /mnt/btrfs-top/timeshift-btrfs/snapshots/2026-06-18_22-43-41/@/etc/myapp/ /etc/myapp/
# drop --dry-run once the list looks right
When you are finished, unmount the top level:
sudo umount /mnt/btrfs-top
(Snapper users, e.g. on openSUSE, have it easier: its snapshots are already browsable under /.snapshots/<N>/snapshot/ — copy the file straight out of there, no extra mount needed.)
Timeshift also has a full command-line interface — what you want over SSH or in a TTY. List, create, and restore snapshots without ever opening the GUI:
# list snapshots (shows the date-stamped names)
sudo timeshift --list
# create one on demand
sudo timeshift --create --comments "before risky change"
# restore a specific snapshot (whole system — see the warning below)
sudo timeshift --restore --snapshot '2026-06-18_22-43-41'
Tip: whichever route you use, Timeshift's restore — the GUI Restore button or
timeshift --restore— rolls back the entire system snapshot, which is overkill and disruptive for one file. For a single file or folder, browse the snapshot andcp -ait out as shown above. (The GUI's Browse button just opens the snapshot in a file manager — the same thing the mount above does.)
Warning: by default Timeshift snapshots only the system subvolume
@— not your personal data in@home. Notice every snapshot path above ends in@, with no@homebeside it. So/etc,/usr, and/varare recoverable here, but a file under/home/youis not in these snapshots — for that, include home (next), or use the trash,btrfs restore, or a backup.
Adding your home folder — and other data — to the snapshots. In Btrfs mode Timeshift works on whole subvolumes, so "adding a folder" means making sure the subvolume that holds it gets snapshotted. There are three command-line routes.
1. Tell Timeshift to include home. The per-user include/exclude setting lives in /etc/timeshift/timeshift.json — the GUI's Settings → Users tab merely edits that file, so you can change it from a terminal (or set it in the GUI once). In Btrfs mode it is all-or-nothing: once home is included, the whole @home subvolume is captured, and an @home appears beside each @ from the next snapshot on. Edit it with Timeshift stopped:
# back up the config, then open it in your editor
sudo cp /etc/timeshift/timeshift.json /etc/timeshift/timeshift.json.bak
sudoedit /etc/timeshift/timeshift.json
# remove your home path from the "exclude" list (and any "/home/**" exclude line),
# so @home is no longer skipped, then save.
2. Or snapshot home yourself with plain Btrfs — no Timeshift at all. This is the most direct command-line approach and works for any subvolume:
# take a read-only snapshot of the live /home (@home) subvolume
sudo btrfs subvolume snapshot -r /home /home/.snap-2026-06-20
# recover from it later by copying files out, then remove it when finished
sudo btrfs subvolume delete /home/.snap-2026-06-20
3. Or let Snapper manage it. Snapper (free software, GPL) snapshots any subvolume you point it at, entirely from the command line, with automatic timelines and cleanup:
# create a Snapper config for /home, then take a snapshot
sudo snapper -c home create-config /home
sudo snapper -c home create --description "before cleanup"
# its snapshots live under /home/.snapshots/<N>/snapshot/ ; list them with:
sudo snapper -c home list
The trade-off: including home makes snapshots grow faster, and a full system restore then rolls your home back too — many people deliberately keep home out of system snapshots and protect it with a separate backup (rsync, BorgBackup, or restic; see the prevention section). For an arbitrary folder on another disk, Timeshift cannot help — point Snapper at that filesystem's subvolume, or use a backup tool.
ZFS
On ZFS (FreeBSD, TrueNAS, or OpenZFS on Linux) snapshots are per-dataset, and every dataset exposes them through a hidden .zfs/snapshot directory — the old files are sitting right there, nothing to mount. List the snapshots first:
# list every snapshot (their names depend on your auto-snapshot tool)
zfs list -t snapshot
Browse the one you want; under .zfs/snapshot/<name>/ the whole dataset appears exactly as it was at that moment:
# browse a snapshot of the tank/home dataset
ls /tank/home/.zfs/snapshot/daily-2026-06-19/
Recover a single file or a whole directory by copying it back out (-a preserves attributes and copies directories recursively):
# one file
cp -a /tank/home/.zfs/snapshot/daily-2026-06-19/report.odt /tank/home/report.odt
# a whole directory
cp -a /tank/home/.zfs/snapshot/daily-2026-06-19/Projects /tank/home/Projects
Warning:
zfs rollback tank/home@daily-2026-06-19also restores from a snapshot, but it reverts the entire dataset and destroys every change made since — use it only when you really want the whole dataset back, never for one file. To get a writable copy of a snapshot without touching the live data, usezfs cloneinstead.
Taking and extending snapshots. ZFS snapshots are instant and take no space until data changes, so take them liberally — one dataset, or a whole tree at once with -r:
# snapshot a single dataset
zfs snapshot tank/home@before-upgrade
# snapshot a dataset and everything beneath it
zfs snapshot -r tank@before-upgrade
To have them taken on a schedule, point a free tool such as sanoid or zfs-auto-snapshot (both free software) at your pool. To put a particular folder under its own snapshot and retention policy, make it its own dataset with zfs create tank/home/important and the snapshots follow it automatically.
LVM
LVM snapshots differ from Btrfs/ZFS in one crucial way: they are not automatic. One only exists if you (or a backup tool) created it before the data was lost. If you have one, mount it read-only and copy files out; if you do not, skip to the undelete tools below. List the volumes and spot snapshots by their Origin column:
# list volumes; a snapshot names its source in the Origin column
sudo lvs -o name,origin,lv_size,data_percent
Mount the snapshot volume read-only, then browse and recover — a single file or a whole directory, exactly as anywhere else:
# mount the snapshot read-only
sudo mkdir -p /mnt/lvm-snap
sudo mount -o ro /dev/vg0/home-snap /mnt/lvm-snap
# browse it
ls /mnt/lvm-snap/home/you/
# recover a single file
sudo cp -a /mnt/lvm-snap/home/you/report.odt /home/you/report.odt
# recover a whole directory
sudo cp -a /mnt/lvm-snap/home/you/Projects /home/you/Projects
# unmount when done
sudo umount /mnt/lvm-snap
Tip: if the volume holds an XFS filesystem it may refuse to mount with a UUID clash against the live one — add
-o ro,nouuid(and-o ro,norecoveryif it complains about a dirty log).
Warning: as with the Btrfs mount earlier, do not
cdinto/mnt/lvm-snapbefore you mount it. A shell already sitting in the mount point keeps looking at the now-hidden empty directory underneath, solsshowstotal 0even after the mount succeeds — browse by absolute path, and if you got caught out, step in again withcd / && cd /mnt/lvm-snap.
Creating snapshots so one exists next time. LVM snapshots are whole-volume, not per-folder, so to protect a folder you snapshot the volume it lives on. A classic (thick) snapshot needs its own space and must be large enough to hold everything that changes before you remove it:
# snapshot the logical volume "home" in volume group "vg0", reserving 5G
sudo lvcreate -s -L 5G -n home-snap /dev/vg0/home
If your volume group uses a thin pool, prefer a thin snapshot — it needs no fixed reserve and will not silently overflow:
# thin snapshot (the volume must live in a thin pool)
sudo lvcreate -s -n home-snap vg0/home
Take the snapshot before any risky work, and automate it from cron or your backup tool so one is always waiting when you need it.
Undeleting by filesystem (with recovery tools)
No snapshot, no open handle, not in the trash? Now we undelete from the filesystem's own structures. Which tool you use depends on the filesystem — check it with lsblk -f /dev/sdX1 or sudo blkid /dev/sdX1. Unmount the partition first (or work from your image).
ext3 / ext4 — the Linux default
extundelete (free software, GPLv2) recovers files from ext3/ext4 using the filesystem journal:
# or pacman -S / dnf install extundelete
sudo apt install extundelete
# Recover everything it can find, into ./RECOVERED_FILES in your CURRENT dir
# (make sure your current dir is on a DIFFERENT disk!)
cd /mnt/otherdisk
sudo extundelete /dev/sdX1 --restore-all
# Or restore one path it knew about
sudo extundelete /dev/sdX1 --restore-file home/you/report.odt
ext4magic (free software, GPLv2+) is a strong second opinion for ext4 and is good at recovering whole directory trees and files deleted within a recent time window:
# recover recently deleted
sudo ext4magic /dev/sdX1 -r -d /mnt/otherdisk/recovered
# recover everything possible
sudo ext4magic /dev/sdX1 -m -d /mnt/otherdisk/recovered
And you always have debugfs, the low-level ext filesystem debugger that ships inside e2fsprogs on every Linux system — no install needed. It can list recently deleted inodes and dump them back out:
sudo debugfs /dev/sdX1
# list deleted inodes
debugfs: lsdel
# dump an inode number from lsdel (here 12345) back out to another disk
debugfs: dump <12345> /mnt/otherdisk/recovered-file
debugfs: quit
Btrfs
Btrfs ships its own undelete in btrfs-progs (free software, GPL). With the filesystem unmounted, btrfs restore walks old metadata roots to pull files back:
sudo btrfs restore -v /dev/sdX1 /mnt/otherdisk/recovered
# If the current tree is too damaged, list older roots and point at one:
sudo btrfs-find-root /dev/sdX1
sudo btrfs restore -t <bytenr> /dev/sdX1 /mnt/otherdisk/recovered
XFS
XFS zeroes an inode's data pointers on delete, so traditional undelete is largely a lost cause — this is the case where carving (next section) is usually the better bet. The community tool xfs_undelete (free software, GPL) can still recover recently deleted files in some cases:
# From the xfs_undelete project; run against an UNMOUNTED xfs partition
sudo xfs_undelete -t '*' -o /mnt/otherdisk/recovered /dev/sdX1
NTFS volumes
If the deleted file was on an NTFS partition (a shared Windows data disk), ntfsundelete — part of ntfs-3g (free software, GPL) and already installed on most systems — does the job:
# list recoverable files
sudo ntfsundelete /dev/sdX1
# recover by pattern
sudo ntfsundelete /dev/sdX1 -u -m '*.docx' -d /mnt/otherdisk/recovered
The Sleuth Kit — one undelete for many filesystems
The Sleuth Kit (free software; package sleuthkit) is a forensic toolkit that reads a filesystem's metadata directly and recovers deleted files by name across most formats — ext2/3/4, FAT12/16/32, exFAT, NTFS, HFS+, and UFS1/2. Two commands do the work: fls lists entries (deleted ones included), and icat extracts a file by its inode number. Point them at an unmounted partition or an image:
# install (or: pacman -S / dnf install sleuthkit)
sudo apt install sleuthkit
# list deleted files recursively; deleted entries are marked with a leading "*"
fls -rd /dev/sdX1
# extract one by the inode number fls printed (e.g. 1234), onto ANOTHER disk
icat /dev/sdX1 1234 > /mnt/otherdisk/recovered-file
For a point-and-click version of the same engine, Autopsy (free software) is its graphical front-end. The Sleuth Kit does not support Btrfs, XFS, ZFS, or F2FS — for those, use the per-filesystem tools above, or carving below.
Other filesystems: FAT/exFAT, HFS+, APFS, UFS, F2FS, ReFS
The formats you meet on USB sticks, Macs, BSD boxes, and phones each have a FOSS route back. Where one has no metadata-aware undelete tool, the fallback is always the same — image the disk and carve it (next section).
- FAT12/16/32, exFAT, vfat — the best-supported family after ext. TestDisk has a built-in Undelete for FAT and exFAT that keeps filenames; fatcat (MIT) lists and extracts deleted FAT entries from the command line; The Sleuth Kit (above) handles them too;
fsck.fat/fsck.exfatrepair the structure. - HFS+ (legacy macOS) — The Sleuth Kit recovers deleted files (
fls -rd/icat); Linux can mount HFS+ read-only and copy intact files straight off;hfsprogsprovidesfsck.hfsplusfor repair. - APFS (modern macOS) — no dedicated undelete, but apfs-fuse (free software, read-only) mounts APFS on Linux including its snapshots, often the cleanest way back; apfsprogs (
apfsck) checks it. Otherwise, carve. - UFS / FFS (BSD) — The Sleuth Kit supports UFS1/UFS2 (
fls/icat); Linux mounts it read-only withmount -t ufs -o ro,ufstype=ufs2;fsck_ffsrepairs it on the BSD side. - F2FS (phones, SD cards) — no FOSS undelete tool and no Sleuth Kit support;
f2fs-toolsgivesfsck.f2fs(repair) anddump.f2fs(inspect inodes). Because it is log-structured, deleted data often lingers, so carving an image works comparatively well here. - ReFS (Windows) — the gap: no mature FOSS ReFS driver exists, so there is no metadata-aware recovery. Image the volume and carve it.
When the metadata is gone: file carving
Sometimes the filesystem itself is destroyed — reformatted, a corrupt superblock, a partition wiped — so there are no directory entries or inodes left to undelete. The answer is carving: ignore the filesystem entirely and scan the raw disk for the signatures that mark the start and end of known file types (the %PDF at the front of a PDF, the JFIF header of a JPEG, and so on). Carving recovers the contents but not the original filenames or folders — you get a pile of f00234.jpg-style files to sort through. It is the most powerful last resort.
PhotoRec — the friendly all-rounder
PhotoRec (free software, GPLv2+; ships with TestDisk in the testdisk package) recognises hundreds of file types and walks you through a simple text menu. Despite the name it recovers far more than photos:
# provides both photorec and testdisk
sudo apt install testdisk
# run against the device, or against an image: sudo photorec rescue.img
sudo photorec /dev/sdX1
Pick the disk/partition, choose where to write (a different disk!), optionally narrow the file types, and let it run. This is the tool to reach for first when the filesystem is unreadable.
foremost and Scalpel — scriptable carvers
foremost (public domain, originally from the US Air Force) and Scalpel (free software, Apache 2.0) are header/footer carvers driven by a config file, handy when you want only certain types:
sudo apt install foremost
sudo foremost -t jpg,pdf,doc -i /dev/sdX1 -o /mnt/otherdisk/recovered
sudo apt install scalpel
sudo scalpel /dev/sdX1 -o /mnt/otherdisk/recovered
For oddball formats, magicrescue (free software, GPL) carves by per-type "recipes" and is worth knowing about for the long tail.
Recovering text with no tool at all
If what you lost is a text file — source code, a config, an essay — and you remember a distinctive phrase from inside it, you can often fish it straight off the raw block device with tools that are on every system. No undelete, no carving, no install.
# Search the raw partition for a line you remember, with context around it.
# -a = treat binary as text, -B/-A = lines of context before/after the match.
sudo grep -a -B5 -A50 'def my_unique_function' /dev/sdX1 > /mnt/otherdisk/found.txt
# Or pull every human-readable string off the device and grep that
sudo strings /dev/sdX1 | grep -A50 'my_unique_marker' > /mnt/otherdisk/found.txt
It is crude and you will scroll through some noise, but for "I just need my one important config file back" it is astonishingly effective — and it works on any filesystem because it ignores the filesystem completely.
Repairing lost partitions and broken filesystems
If the problem is bigger than one file — a whole partition vanished, or a filesystem won't mount — TestDisk (free software, GPLv2+; same testdisk package as PhotoRec) is the classic rescue tool. It can rebuild a deleted or overwritten partition table, fix a damaged boot sector, and make a lost filesystem mountable again — often recovering every file in one move:
# note: the whole DISK (sdX), not a partition
sudo testdisk /dev/sdX
It is menu-driven: choose the disk, let it analyse, and it will offer to write back a corrected partition table or copy files off the recovered partition.
Warning:
fsckcan repair a corrupt filesystem, but on a damaged disk an aggressive repair can also destroy recoverable data — it is a repair tool, not a recovery tool. Image the disk withddrescuefirst, then runfsckagainst the image (or with the original safely backed up). After a successfulfsck, also checklost+foundat the root of the filesystem — orphaned files land there.
Which method should I use?
Start at the top row that matches your situation; the methods are roughly ordered from "easiest and most reliable" to "last resort".
| Your situation | Try this first | Tool (all FOSS) |
|---|---|---|
| Deleted in a file manager | Restore from trash | trash-cli / gio / file manager |
| File still open in a running program | Copy from the open handle | lsof + /proc/<pid>/fd |
| You had snapshots/backups | Copy out of the snapshot | Btrfs / ZFS / LVM / Timeshift |
| Just deleted on ext4, FS intact | Undelete via the journal | extundelete, ext4magic, debugfs |
| Deleted on Btrfs / XFS / NTFS | The matching undelete tool | btrfs restore, xfs_undelete, ntfsundelete |
| Deleted on FAT/exFAT, HFS+, or UFS | Metadata-aware undelete | The Sleuth Kit (fls/icat), TestDisk, fatcat |
| Filesystem reformatted or corrupt | Carve by file signature | PhotoRec, foremost, Scalpel |
| A lost text file you can quote | Grep the raw device | grep -a, strings |
| Whole partition gone / won't mount | Rebuild the partition table | TestDisk |
| Disk is failing / has bad sectors | Image it, then recover from the copy | GNU ddrescue |
Prevention: make next time a non-event
Recovery is a gamble you can usually avoid. A little setup turns "I lost a file" from a panic into a thirty-second copy — and all of it is free and open source:
- Use a trash on the command line. Install
trash-cliand reach fortrash putinstead ofrm. Most accidental deletions never become emergencies. - Take automatic snapshots. On Btrfs, set up Timeshift or Snapper; on ZFS, schedule periodic snapshots. Restoring becomes a file copy, with no race against new writes.
- Keep real backups. A scheduled
rsyncto another disk, or BorgBackup / restic (both free software) for versioned, deduplicated, encrypted backups, beats every recovery tool on this page — because the data was never lost in the first place.
Quick reference
- Stop writing to the affected disk; recover onto a different disk.
sudo ddrescue -d -r3 /dev/sdX1 rescue.img rescue.map— image a failing disk first.sudo lsof +L1thencp /proc/<pid>/fd/<fd> out— deleted-but-still-open file.trash-list/trash-restore— recover from the desktop trash.- Snapshots:
btrfs subvolume list /,.zfs/snapshot/,lvs— copy the file out. sudo extundelete /dev/sdX1 --restore-all— ext3/ext4 undelete (alsoext4magic,debugfs lsdel).sudo btrfs restore/sudo ntfsundelete/xfs_undelete— per-filesystem undelete.fls -rd /dev/sdX1thenicat /dev/sdX1 <inode> > out— The Sleuth Kit undelete (ext, FAT/exFAT, NTFS, HFS+, UFS).sudo photorec /dev/sdX1— carve files when the filesystem is gone (alsoforemost,scalpel).sudo grep -a -B5 -A50 'phrase' /dev/sdX1— pull a known text file off the raw device.sudo testdisk /dev/sdX— rebuild a lost partition / unmountable filesystem.
Tools used in this guide (all free and open source)
Every program named above is free and open source. Here is each one with its project page and license, grouped by where it appears — nothing on this page is paid, proprietary, or cloud.
Imaging and safety
- GNU ddrescue — GPLv3
- dd (GNU coreutils) — GPLv3
Trash
Open file handles
- lsof — permissive (Purdue/BSD-style) license
Snapshots
- Timeshift — GPL
- Snapper — GPLv2+
- btrfs-progs (btrfs restore) — GPLv2
- OpenZFS — CDDL-1.0
- sanoid — GPLv3
- zfs-auto-snapshot — GPLv2
- LVM2 (lvs, lvcreate) — GPLv2
Undelete by filesystem
- extundelete — GPLv2
- ext4magic — GPLv2+
- e2fsprogs (debugfs) — GPLv2
- xfs_undelete — GPLv3
- ntfs-3g (ntfsundelete) — GPLv2
- The Sleuth Kit — IPL / CPL / GPL
- Autopsy — Apache 2.0
- fatcat — MIT
- apfs-fuse — GPLv2
- apfsprogs — GPLv2
- hfsprogs — APSL 2.0 (an OSI-approved license; Debian packages it as non-free)
- f2fs-tools — GPLv2
- dosfstools (fsck.fat) — GPLv3
- exfatprogs (fsck.exfat) — GPLv2
File carving
- PhotoRec and TestDisk — GPLv2+
- foremost — public domain (US Government work)
- Scalpel — Apache 2.0
- Magic Rescue — GPLv2
Text recovery
- GNU grep — GPLv3
- GNU binutils (strings) — GPLv3
Backups (prevention)
- rsync — GPLv3
- BorgBackup — BSD-3-Clause
- restic — BSD-2-Clause