Skip to content

Instantly share code, notes, and snippets.

Last active April 22, 2024 20:06
Show Gist options
  • Save Changaco/45f8d171027ea2655d74 to your computer and use it in GitHub Desktop.
Save Changaco/45f8d171027ea2655d74 to your computer and use it in GitHub Desktop.
# btrfs-undelete
# Copyright (C) 2013 Jörg Walter <>
# This program is free software; you can redistribute it and/or modify it under
# the term of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or any later version.
if [ ! -b "$1" -o -z "$2" -o -z "$3" ]; then
echo "Usage: $0 <dev> <file/dir> <dest>" 1>&2
echo "This program tries to recover the most recent version of the"
echo "given file or directory (recursively)"
echo "<dev> must not be mounted, otherwise this program may appear"
echo "to work but find nothing."
echo "<file/dir> must be specified relative to the filesystem root,"
echo "obviously. It may contain * and ? as wildcards, but in that"
echo "case, empty files might be 'recovered'. If <file/dir> is a"
echo "single file name, this program tries to recover the most"
echo "recent non-empty version of the file."
echo "<dest> must be a writable directory with enough free space"
echo "to hold the files you're trying to restore."
exit 1
# quote regex special characters
# treat shell wildcards specially
# extract number of slashes in order to get correct number of closing parens
# build final regex
roots="$(mktemp --tmpdir btrfs-undelete.roots.XXXXX)"
out="$(mktemp --tmpdir="$3" -d btrfs-undelete.XXXXX)"
cd $out
trap "rm $roots" EXIT
trap "rm -r $out &> /dev/null; exit 1" SIGINT
echo -ne "Searching roots..."
btrfs-find-root -a "$dev" 2>&1 \
| grep ^Well \
| sed -r -e 's/Well block ([0-9]+).*/\1/' \
| sort -rn >$roots || exit 1
max="$(wc -l <$roots)"
while read id; do
echo -e "Trying root $id... ($i/$max)"
btrfs restore -t $id --path-regex "$regex" "$dev" . &>/dev/null
if [ "$?" = 0 ]; then
found=$(find . -type f ! -size 0c | wc -l)
if [ $found -gt 0 ]; then
echo "Recovered $found non-empty file(s) into $out"
exit 0
find . -type f -size 0c -exec echo "Found {} but it's empty" \; -delete
done <$roots
rm -r $out
echo "Didn't find '$file'"
exit 1
Copy link

illwieckz commented Jan 24, 2021

To always answer a you can do:

yes a | btrfs restore -i /dev/nvme1n1p1 /mnt/disk2/nvme1n1p1_restore

Anyhow, it was restored ^^

Maybe it's incomplete?

Copy link

Fr-Dae commented Mar 9, 2021

(Lubuntu 18.04x64)

hello, I would like to have some pressision on your script

To execute it, I have to copy and paste it into a text editor

saved it under the .sh extension and make it executable right?


I have rescement I deleted by mistake a very important folder on my secondary hard drive (/ dev / sda3) an HDD
The file contained only zip that I want to receive
/dev/sda3 = /mnt/38b05da3-7068-45b9-bc0a-0b944f15487f

A friend recommended me the following monate options to make the disk read alone thus avoiding the old data, for limiting the loss.
that right for you ?

I plugged in an external hard drive, because my systeme ssd are prety small
/dev/sdc1 = /media/dae-rog/data-backup

My question is, are your tools like?
Where is it asking for data once executed?
Or do I manually be edited?

Dae#5125 on discord

Copy link

Fogapod commented Apr 11, 2021

Thank you

Copy link

Thank you so much! This saved me 12 days.

Copy link

amazing works! saved my monthes!

Copy link

kulak commented Jul 17, 2023

When working with subvolumes make sure to include subvolume data. For example, to extract tree of files from @data subvolume and user /home/accident use command:

 btrfs-undelete /dev/mapper/container '@data/home/accident' /tmp/extraction-location

This will include all fines under /home/accident.

Copy link

" must not be mounted, otherwise this program may appear
to work but find nothing."

can I unmount dev on a running system?

Copy link

sirus20x6 commented Oct 26, 2023

oh I get it. please change the wording of dev to source device

Copy link

can this also find the next most recent deleted file? I think I got most of what I wanted back except for a few lines that had been touched more recently

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment