-
Star
(178)
You must be signed in to star a gist -
Fork
(32)
You must be signed in to fork a gist
-
-
Save Changaco/45f8d171027ea2655d74 to your computer and use it in GitHub Desktop.
| #!/bin/bash | |
| # btrfs-undelete | |
| # Copyright (C) 2013 Jörg Walter <[email protected]> | |
| # 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 | |
| echo "This program tries to recover the most recent version of the" | |
| echo "given file or directory (recursively)" | |
| echo | |
| echo "<dev> must not be mounted, otherwise this program may appear" | |
| echo "to work but find nothing." | |
| echo | |
| 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 | |
| echo "<dest> must be a writable directory with enough free space" | |
| echo "to hold the files you're trying to restore." | |
| exit 1 | |
| fi | |
| dev="$1" | |
| file="$2" | |
| file="${file#/}" | |
| file="${file%/}" | |
| regex="${file//\\/\\\\}" | |
| # quote regex special characters | |
| regex="${regex//./\.}" | |
| regex="${regex//+/\+}" | |
| regex="${regex//|/\|}" | |
| regex="${regex//(/\(}" | |
| regex="${regex//)/\)}" | |
| regex="${regex//\[/\[}" | |
| regex="${regex//]/\]}" | |
| regex="${regex//\{/\{}" | |
| regex="${regex//\}/\}}" | |
| # treat shell wildcards specially | |
| regex="${regex//\*/.*}" | |
| regex="${regex//\?/.}" | |
| # extract number of slashes in order to get correct number of closing parens | |
| slashes="${regex//[^\/]/}" | |
| # build final regex | |
| regex="^/(|${regex//\//(|/}(|/.*${slashes//?/)}))\$" | |
| 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 | |
| echo | |
| i=0 | |
| max="$(wc -l <$roots)" | |
| while read id; do | |
| ((i+=1)) | |
| 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 | |
| fi | |
| find . -type f -size 0c -exec echo "Found {} but it's empty" \; -delete | |
| fi | |
| done <$roots | |
| rm -r $out | |
| echo "Didn't find '$file'" | |
| exit 1 |
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.
" must not be mounted, otherwise this program may appear
to work but find nothing."
can I unmount dev on a running system?
oh I get it. please change the wording of dev to source device
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
Thank you. Now I just need to find out why the backup wasn't working ...
Recovered a file after I accidentally deleted it, thanks <3
will this work on my lost partition?
the data is still there except for a 500 mb at the start.
will the directories be intact??
amazing works! saved my monthes!