Recover accidentally deleted files on Linux
Linux has no recycle bin on servers, so act in this order: stop writing to the affected filesystem, rescue any deleted file a program still holds open, then look in snapshots and backups. Undelete tools come last, work best on an unmounted copy of the disk, and often return files without names.
Do this first.
- Stop whatever writes to that filesystem (the application, log-heavy services, cron jobs). Every new write can overwrite the deleted data.
- Do not reboot and do not stop the program that used the file until you have checked
/procbelow: an open file disappears for good when the program exits. - Do not install recovery tools onto the same filesystem, and never save recovered files to it.
- Check snapshots and backups before trying any undelete tool.
Common situations
- An
rmorrm -rfon the wrong path, often from a script with an empty variable. - A file overwritten with
>instead of appended with>>. That is not a deletion: the old content is gone from the file, so only snapshots and backups can help. - A deleted log or database file that a running service still writes to, so disk space does not come back (see also Disk full).
- A package-managed config file or program removed by mistake.
1. Stop writing to the disk
Find the filesystem and its type, because the type decides your options:
df -hT /var/www/site
findmnt -T /var/www/site
If it is a separate data filesystem, stop the services using it and remount it read-only. The remount fails with "target is busy" if something still has files open for writing; sudo lsof /srv shows what.
sudo systemctl stop myapp # stops the service
sudo mount -o remount,ro /srv
If the file was on the root filesystem, keep activity low and plan to work from a rescue or live system later. On SSDs and many cloud disks, a scheduled fstrim (the util-linux manual suggests weekly for most servers) tells the device which blocks are free, and the device may then erase them. Recovery chances on such disks drop quickly.
2. Rescue files that are still open
When you delete a file that a process still has open, the data stays on disk until the process closes it. Each process's /proc/<pid>/fd folder holds links to its open files, and deleted ones are shown with (deleted). The lsof manual says +L1 selects "open files that have been unlinked".
sudo lsof -nP +L1
# or without lsof:
sudo find /proc/[0-9]*/fd -lname '*(deleted)' -printf '%p -> %l\n' 2>/dev/null
sudo ls -l /proc/1234/fd # find the fd number, e.g. 7
sudo cp /proc/1234/fd/7 /mnt/rescue/app.db
Copy to a different disk, mounted here at /mnt/rescue, or stream it to another machine with sudo cat /proc/1234/fd/7 | ssh you@otherhost 'cat > app.db'. If the program is still writing, the copy is a moment-in-time picture; for a database, treat it like a crash copy and let the database check it on start (see Database won't start). Copy first, then put the file back in place and restart the service.
3. Look in snapshots
Snapshots taken before the deletion are the fastest clean source. Once you find the file in a snapshot, writing to the live filesystem is safe again.
ZFS
zfs list -t snapshot -o name,creation
ls /srv/.zfs/snapshot/ # works even when .zfs is hidden
cp -a /srv/.zfs/snapshot/daily-2026-11-02/site/config.php /srv/site/
OpenZFS mounts each snapshot on demand under .zfs/snapshot at the root of the dataset. The snapdir property only controls whether .zfs is listed; it is hidden by default but you can still enter it.
Btrfs and snapper
sudo btrfs subvolume list -s /
sudo snapper list # openSUSE and others using snapper
sudo cp -a /.snapshots/42/snapshot/etc/nginx/nginx.conf /etc/nginx/
A Btrfs snapshot does not include nested subvolumes; they appear as empty folders inside it.
LVM
LVM only helps if a snapshot existed before the deletion. Mount it read-only and copy out. XFS refuses to mount two filesystems with the same UUID, so add nouuid:
sudo lvs
sudo mkdir -p /mnt/snap
sudo mount -o ro /dev/vg0/data-snap /mnt/snap # ext4
sudo mount -o ro,nouuid /dev/vg0/data-snap /mnt/snap # XFS
Also check your hosting provider's disk snapshots: you can usually attach one to the server as a second disk and copy files out.
4. Restore from backup
# restic: find which snapshots contain the file, then restore it to a scratch folder
restic find config.php
restic restore latest --target /root/restore --include /var/www/site/config.php
# Borg: list, then extract (paths without leading slash, into the current folder)
borg list ::web1-2026-11-02T02:15:01 | grep config.php
mkdir -p /root/restore && cd /root/restore && borg extract ::web1-2026-11-02T02:15:01 var/www/site/config.php
Restore to a separate folder, check the file, then copy it into place. More in Ransomware-proof backups.
Files that belong to a package
If you deleted a program or a default config file, reinstall the package instead. On Debian and Ubuntu, deleted config files are not put back unless you ask with --force-confmiss:
# Debian / Ubuntu
dpkg -S /etc/nginx/nginx.conf # which package owns it
sudo apt install --reinstall -o Dpkg::Options::=--force-confmiss <package>
# RHEL, Rocky, AlmaLinux, Fedora
rpm -qf /etc/nginx/nginx.conf
sudo dnf reinstall <package>
5. Undelete tools: the last resort
First make an image of the partition onto a different disk and work on the image, so a mistake cannot make things worse. Run this with the partition unmounted or read-only:
sudo dd if=/dev/sdb1 of=/mnt/rescue/sdb1.img bs=4M status=progress
If the deleted files were on the root filesystem, boot a rescue or live system that already has the tools, rather than installing them onto the damaged disk. TestDisk and PhotoRec come in the testdisk package (Debian/Ubuntu; EPEL on RHEL-family).
| Tool | Filesystems | Limits |
|---|---|---|
| extundelete | ext3, ext4 with a journal | Uses old inode copies in the journal, so success falls as the journal is reused. Partition must be unmounted or read-only. No links or extended attributes. Last release 0.2.4, January 2013. |
| TestDisk | Undelete on FAT, exFAT, NTFS, ext2 | No undelete for ext3, ext4 or XFS. Useful for lost partitions and for copying files out of a deleted ext partition. |
| PhotoRec | Ignores the filesystem; lists ext2/3/4, FAT, NTFS, exFAT, HFS+ | Finds files by known headers, so names, dates and folders are lost. Opens the source read-only. Output must go to another partition. |
| xfs_undelete | XFS | Community tool, not part of xfsprogs. Cannot recover names or paths. Skips files with more than 21 extents on typical inodes. Output must be on another filesystem. |
# Run from a folder on the rescue disk
cd /mnt/rescue
sudo extundelete /dev/sdb1 --restore-all # writes to ./RECOVERED_FILES
sudo photorec /mnt/rescue/sdb1.img # interactive; choose an output folder on the rescue disk
sudo testdisk /dev/sdb # interactive; partition recovery
Expect partial results. PhotoRec can return thousands of files named by number; sort them by type and size, and use grep -rl for a known string to find text files such as configs and scripts.
How to confirm it is fixed
- The recovered file opens and has the expected content and size.
- Ownership and permissions match the original (
ls -l, compare with a backup or similar file). - The service that uses it starts and works.
- Any read-only remount has been undone:
sudo mount -o remount,rw /srv.
Prevent it next time
- Run backups with tested restores (Ransomware-proof backups), plus local snapshots (ZFS, Btrfs with snapper, or LVM thin snapshots) for quick undo.
- In scripts, use
set -uand write"${DIR:?}", so an unset or empty variable stops the script instead of turningrm -rf "$DIR"/*intorm -rf /*. - Interactively,
rm -Iprompts once before removing more than three files or removing recursively. - Keep configuration in version control (for example
/etcin git).
When to call a professional
If the disk makes noises, shows I/O errors in dmesg, or the data is worth more than a recovery service costs, stop and contact a data recovery company or your hosting provider. Every extra attempt on a failing disk lowers the chances.
Sources
- proc_pid_fd(5), Linux manual pages
- lsof(8), Linux manual pages
- fstrim(8), Linux manual pages
- rm(1), Linux manual pages
- zfs-snapshot(8), OpenZFS documentation
- zfsprops(7), OpenZFS documentation
- btrfs-subvolume, Btrfs documentation
- lvcreate(8), Linux manual pages
- Restoring from backup, restic documentation
- borg extract, BorgBackup documentation
- extundelete project page
- TestDisk, CGSecurity
- PhotoRec, CGSecurity
- xfs_undelete project page