2

I am trying to recover files after a crash of a btrfs filesystem using:

btrfs restore --path-regex 'regex' -sv -D /dev/sdXX /mnt/destination

for example, to retrieve all files in /snapshots/@_2018-06-01T23:29:33-04:00.preupgrade/ I tried following http://www.kossboss.com/?p=2277 and got (among many other attempts):

^/(|/snapshots(|/\@\_2018\-06\-01T23\:29\:33\-04\:00\.preupgrade(|/.*)))$

This failed to select any files. I have tried 5 hrs of things. I am at a loss.

What am I doing wrong? How can I make it work?

It needs to be selective for a number of reasons. Manly because it fails in the middle and I need to script selective attempts to retrieve viable files beyond the fails.

alexander.polomodov
  • 1,068
  • 3
  • 10
  • 14
rick
  • 21
  • 1
  • 2
  • Why the pipe `|` characters in your regex? – Lieven Keersmaekers Aug 30 '18 at 05:33
  • 1
    I am SO glad you asked that!! Because the man page says to, and because doing it the way EVERY regex tutorial tells me doesn't work either. From the man page: --path-regex restore only filenames matching a regular expression (regex(7)) with a mandatory format ^/(|home(|/username(|/Desktop(|/.*))))$ The format is not very comfortable and restores all files in the directories in the whole path, so this is not useful for restoring single file in a deep hierarchy. – rick Sep 01 '18 at 19:19

2 Answers2

1

btrfs restore scans through the filesystem starting at the root and compares each entry to the regex. If the path matches the regex and it is a directory, it will scan that directory. If it's a file and it matches, it will restore it.

What this means is that every parent directory of the file/directory that you're trying to restore needs to be matched by the regex to ensure that the restore program will eventually get to it.

What the sample regex from the manpage ^/(|home(|/username(|/Desktop(|/.*))))$ really means is, "/ followed by nothing or home followed by nothing or /username followed by nothing or /Desktop followed by nothing or /.*", which is equivalent to "/ or /home or /home/username or /home/username/Desktop or /home/username/Desktop/.*".

The unsual (|/foo) construction is matching nothing or /foo and the nested capture groups are just to be able to nest the or statements.

For readability's sake, I would suggest writing the regex as ^(/|/home|/home/username|/home/username/Desktop/|/home/username/Desktop/.*)$, which I think is a lot clearer as to what it is doing.

0

Ok. I might have figured it out. Got it to work anyway. The colons and dashes were not escapable and these are NOT normal regex. For the colons and dashes and such I was able to simply match "."

Following the instructions from the man page, included below for clarity, I got this:

# restore specific path:
# "@_2018-08-17_08.18.30.preupgrade"
btrfs restore --path-regex   \
'^/(|snapshots(|/@\_2018.*08.17.*preupgrade(|/.*)))$'  \
-s  -o  /dev/sda5 /media/outputdir/

This still leaves the question of what is going on with the regex format?

from the man page: --path-regex restore only filenames matching a regular expression (regex(7)) with a mandatory format

       ^/(|home(|/username(|/Desktop(|/.*))))$

The format is not very comfortable and restores all files in the directories in the whole path, so this is not useful for restoring single file in a deep hierarchy.

rick
  • 21
  • 1
  • 2