rm eating everything, here’s a bit of my solution

Everyone’s who’s worked in a computer environment which assumes you know what you’re doing knows that you don’t in fact always know what you’re doing. So I like a couple of things to be true. First, I want the machine to do what I say when I say it. Second, I want to be able to undo whatever it is I just did when I realize I just deleted a bunch of critical files. My solution to this comes in a few parts. First, I make a trash folder which holds files on the way out. Second, when I say rm, I actually just move those files to the trash folder, which is very fast. Then later, I zip the files in the trash, so while they’re sitting there they don’t take up any space. Now the file is gone from the working directory and most of the space is reclaimed. And if I need the file back I know where to look to get it. I might need to unzip it, but it’s there. And I never need to empty the trash, because every day those files older than 30 days old go buh-bye. So machinery which lets me recover files, doesn’t slow anything down, and requires no maintenance. Check. I might recommend testing everything on the command line before you let if loose.

First, make a trash directory, on ubuntu one is made for you, namely ~/.local/share/Trash/files/ . I put this in my .bashrc

export TRASH=”~/.local/share/Trash/files/”

though of note I use the full path here. I think because of the way we’re going to use bash substitutions it needs to be a full path. I replace rm with my own version, which lives in ~/bin/ which is in the path before the real rm.

#!/usr/bin/perl
# safer rm
use strict;
my $carg;
my $cmd;
my $trash = $ENV{'TRASH'};
if($trash eq "")
{
     print "\$TRASH is empty string. exiting";
     exit(0);
}
for(my $i=0; $i < $#ARGV+1; $i++)
{
     $carg = $ARGV[$i];
     $carg =~ s/\/$//g;#does what?
     if(!(-e $carg)){next;}
     system("touch $carg && /bin/rm -rf $trash/$carg; mv $carg $trash");
}

I make two additions to the crontab:
30 3 * * * empty_trash
*/30 * * * * zip_trash

and then there’s empty_trash and zip_trash:
#!/bin/bash
# empty_trash
if [ "$TRASH" == "" ]; then
     echo '$TRASH is not set, bailing.'
     exit
else
     find $TRASH -xdev -mindepth 1 -mtime +14 -print0|xargs -P 2 -n 10 -0 --no-run-if-empty /bin/rm -r
fi

#!/bin/bash
# zip_trash
if [ "$TRASH" == "" ]; then
     echo '$TRASH is not set, bailing.'
     exit
else
     find $TRASH -mindepth 1 -xdev -type f -print0 |xargs --null -P 7 -n 1 --no-run-if-empty nice -n 19 gzip -f -q 2>&1
fi

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: