Today had some important markdown file that accidentally deleted on my SSD and had to go over the recovery of it.

All I did was this:


run sudo systemctl status fstrim.timer to check how often TRIM runs on my system (apparently it runs weekly and the next scheduled run was in 3 days)

run sudo pacman -S testdisk

run sudo photorec

choose the correct partition where the files were deleted

choose filesystem type (ext4)

choose a destination folder where to save recovered files

start recovery

10-15 minutes and it’s done.

open nvim in parent folder and grep for content in the file that I remember adding today


That’s it - the whole process was so fast. No googling through 10 different sites with their shitty flashy UIs promising “free recovery,” wondering whether this is even trustworthy to install on your machine, dealing with installers that’ll sneak in annoying software if you click too fast, only to have them ask for payment later. No navigating complex GUIs either.

I was so thankful for this I actually donated to the maintainers of the software. Software done right.

  • redjard@lemmy.dbzer0.com
    link
    fedilink
    arrow-up
    25
    ·
    1 day ago

    Last time I deleted a plaintext file I just grepped for it.
    cat /dev/nvme0n1 | strings | grep -n "text I remember"

    Had to hone in on the location with head -c and tail -c after I found it, then simply did a cat /dev/nvme0n1 | tail -c -123456789012 | head -c 3000 > filerec and trimmed the last filesystem garbage from the ends manually.

    • Gobbel2000@programming.dev
      link
      fedilink
      arrow-up
      4
      ·
      11 hours ago

      That was so eye-opening for me when I figured out you can just grep a block device for files unlinked by the file system but not yet physically overwritten. Magically reanimating lost files can be such an incredibly simple operation.

        • redjard@lemmy.dbzer0.com
          link
          fedilink
          arrow-up
          3
          ·
          21 hours ago

          It makes the command easier to edit here. Put the various forms across my use next to each other and it becomes apparent:

          cat /dev/nvme0n1 | strings | grep -n "text I remember"
          cat /dev/nvme0n1 | tail -c -100000000000 | head -c 50000000000 | strings | grep -n "text I remember"
          cat /dev/nvme0n1 | tail -c -123456789012 | head -c 3000 > filerec

          compare that to

          strings /dev/nvme0n1 | grep -n "text I remember"
          tail /dev/nvme0n1 -c -100000000000 | head -c 50000000000 | strings | grep -n "text I remember"
          tail /dev/nvme0n1 -c -123456789012 | head -c 3000 > filerec

          where I have to weave the long and visually distracting partition name between the active parts of the command.
          The cat here is a result of experiencing what happens when not using it.

          Worse, some commands take input file arguments in weird ways or only allow them after the options, so when taking that into account the generic style people use becomes

          strings /dev/nvme0n1 | grep -n "text I remember"
          tail -c -100000000000 /dev/nvme0n1 | head -c 50000000000 | strings | grep -n "text I remember"
          tail -c -123456789012 /dev/nvme0n1 | head -c 3000 > filerec

          This is what I’d expect to run across in the wild, and also for example what ai spits out when asked how to do this. You’ll take my stylistic cats over my dead body

          • thingsiplay@beehaw.org
            link
            fedilink
            arrow-up
            2
            ·
            edit-2
            16 hours ago

            In that case I would prefer using variables for the filename:

            file="/dev/nvme0n1"
            text="text I remember"
            strings "${file}" | grep -n "${text}"
            tail -c -100000000000 "${file}" | head -c 50000000000 | strings | grep -n "${text}"
            tail -c -123456789012 "${file}" | head -c 3000 > filerec
            

            Even if it’s in the terminal, a temporary variable helps a lot. And for a series of commands I would probably end up writing a simple script or Bash function to share.

            • redjard@lemmy.dbzer0.com
              link
              fedilink
              arrow-up
              2
              ·
              15 hours ago

              I could do a script if I knew what I was gonna do ahead of time, or would write one later if I was gonna do it more often.

              A variable in the shell is fine, but I still have to skip over it to change the first command, it still breaks up the flow a bit more than not having that "$file" in there at all.
              Also if I interrupt the work (or in this case have to let it run for a while), or if I wanna share this with others for whatever reason, I don’t have to hunt for the variable definition, and don’t run any risk of fetching the wrong one if I changed it. Getting by without variables makes the command self-contained.

              And it still maintains the flow of left to right, it’s simply easier to take the tiny well-known packet of cat file and from that point pipe the information ever rightwards, than to see a tail, then read the options, and only then see the far more important start of where the information comes from, to the continue on with the next processing step.
              Any procedural language is always as left to right as possible.

              If you really want to avoid the cat, I have yet another different option for you:
              < /dev/nvme0n1 strings | grep -n "text I remember"
              < /dev/nvme0n1 tail -c -100000000000 | head -c 50000000000 | strings | grep -n "text I remember"
              < /dev/nvme0n1 tail -c -123456789012 | head -c 3000 > filerec

              This ofc you can again extend with ${infile} and ${recfile} if the context makes it appropriate.

              • thingsiplay@beehaw.org
                link
                fedilink
                arrow-up
                2
                ·
                15 hours ago

                I understand the reason why you do it this way. Hardcoded and be explicit has its advantage (but also disadvantage). I was just saying that I personally prefer using variables in a case like this. Especially when sharing, because the user needs to edit a single place only. And for variables, it has the advantage being a bit more flexible and easier to read and change for many commands. But that’s from someone who loves writing aliases, scripts and little programs. It’s just a different mindset and none way is wrong or correct. But probably not worth it complicating stuff for one off commands.

                And for the cat thing, I am not that concerned about it and just took the last example in your post (because it seemed to the most troublesome). I personally avoid cat when I think about it, but won’t go out of my way to hunt it down. I only do so, if performance is in any way critical issue (like in a loop).

      • redjard@lemmy.dbzer0.com
        link
        fedilink
        arrow-up
        2
        ·
        22 hours ago

        I don’t like to use < in combination with pipes, I find it harder to read. One is left to right the other right to left, and < is also just plain weird in its specifics.
        cat is a stylistic choice avoiding needless notational complexity

        • MonkderVierte@lemmy.zip
          link
          fedilink
          arrow-up
          2
          ·
          21 hours ago

          strings /dev/nvme0n1 | grep -n "text I remember"

          tail -c -123456789012 /dev/nvme0n1 | head -c 3000 > filerec

          No need for < complexity either.

          • redjard@lemmy.dbzer0.com
            link
            fedilink
            arrow-up
            2
            ·
            21 hours ago

            Oh right I misunderstood.
            I didn’t do that because I was planning to switch out strings in that line. First inserting the tail and head before it to hone in on the position, then removing it entirely to not delete “non-string” parts of my file like empty newlines.

            cat /dev/nvme0n1 | strings | grep -n "text I remember"
            cat /dev/nvme0n1 | tail -c -100000000000 | head -c 50000000000 | strings | grep -n "text I remember"
            cat /dev/nvme0n1 | tail -c -123456789012 | head -c 3000 > filerec

            This would be the loose chain of commands I went through, editing one into the next. It’s nice keeping the “constants” like the drive device that are hard to type static. That way mentally for me the command starts only after the first pipe.