Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 26 Jul 2005 10:05:05 +0300
From:      Peter <peterpub1@aboutsupport.com>
To:        Karel Miklav <karel@inetis.com>
Cc:        freebsd-questions@freebsd.org
Subject:   Re: undelete in FreeBSD?
Message-ID:  <42E5E0A1.7010600@aboutsupport.com>
In-Reply-To: <42E5D145.4050200@inetis.com>
References:  <20050726024807.E825D1D936@imss.sgp.fujixerox.com> <42E5D145.4050200@inetis.com>

next in thread | previous in thread | raw e-mail | index | archive | help
Hi,

this tip is taken from BSD hacks
book(http://www.amazon.com/exec/obidos/tg/detail/-/0596006799/002-3776521-4670458?v=glance)

Create a Trash Directory


Save "deleted" files until you're really ready to send them to the bit 
bucket.
One of the first things Unix users learn is that deleted files are 
really, really gone. This is
especially true at the command line where there isn't any Windows-style 
recycling bin to
rummage through should you have a change of heart regarding the fate of 
a removed file.
It's off to the backups! (You do have backups, don't you?)
Fortunately, it is very simple to hack a small script that will send 
removed files to a custom
trash directory. If you've never written a script before, this is an 
excellent exercise in how
easy and useful scripting can be.
Since a script is an executable file, you should place your scripts in a 
directory that is in
your path. Remember, your path is just a list of directories where the 
shell will look for
commands if you don't give them full pathnames. To see your path:
% echo $PATH
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/games:/usr/local/sbin:/usr/
local/bin:/usr/X11R6/bin:/home/dru/bin
In this output, the shell will look for executables in the bin 
subdirectory of dru's home
directory. However, it won't look for executables placed directly in my 
home directory, or
/home/dru. Since bin isn't created by default, I should do that first:
% cd
% mkdir bin
As I create scripts, I'll store them in /home/dru/bin, since I don't 
have permission to store
them anywhere else. Fortunately, no one else has permission to store 
them in my bin
directory, so it's a good match.
The scripts themselves contain at least three lines:
#!/bin/sh
# a comment explaining what the script does
the command to be executed
The first line indicates the type of script by specifying the program to 
use to execute the
script. I've chosen to use a Bourne script because that shell is 
available on all Unix systems.
Your script should also have comments, which start with the # character. 
It's surprising how
forgetful you can be six months down the road, especially if you create 
a lot of scripts. For
this reason, you should also give the script a name that reminds you of 
what it does.
The third and subsequent lines contain the meat of the script: the 
actual command(s) to
execute. This can range from a simple one-liner to a more complex set of 
commands,
variables, and conditions. Fortunately, we can make a trash script in a 
simple one-liner.

Let's start with this variant, which I found as the result of a Google 
search:
% more ~/bin/trash
#!/bin/sh
# script to send removed files to trash directory
mv $1 ~/.trash/
You should recognize the path to the Bourne shell, the comment, and the 
mv command.
Let's take a look at that $1. This is known as a positional parameter 
and specifically refers
to the first parameter of the trash command. Since the mv commands takes 
filenames as
parameters, the command:
mv $1 ~/.trash/
is really saying, mv the first filename, whatever it happens to be, to a 
directory called .trash
in the user's home directory (represented by the shell shortcut of ~). 
This move operation is
our custom "recycle."
Before this script can do anything, it must be set as executable:
% chmod +x ~/bin/trash
And I must create that trash directory for it to use:
% mkdir ~/.trash
Note that I've chosen to create a hidden trash directory; any file or 
directory that begins
with the . character is hidden from normal listings. This really only 
reduces clutter, though,
as you can see these files by passing the -a switch to ls. If you also 
include the F switch,
directory names will end with a /:
% ls -aF ~
.cshrc .history .trash/
bin/ images/ myfile
Now comes the neat part of the hack. I want this script to kick in every 
time I use rm. Since
it is the shell that executes commands, I simply need to make my shell 
use the trash
command instead. I do that by adding this line to ~/.cshrc:
alias rm trash
That line basically says: when I type rm, execute trash instead. It 
doesn't matter which
directory I am in. As long as I stay in my shell, it will mv any files I 
try to rm to my hidden
trash directory.
Whenever you create a script, always test it first. I'll start by 
telling my shell to reread its
configuration file:
% source ~/.cshrc
Then, I'll make some test files to remove:
% cd
% mkdir test
% cd test
% touch test1
% rm test1
% ls ~/.trash
test1
Looks like the script is working. However, it has a flaw. Have you 
spotted it yet? If not, try
this:
% touch a aa aaa aaaa
% rm a*
% ls ~/.trash
test1 a
% ls test
aa aaa aaaa
What happened here? I passed the shell more than one parameter. The a* 
was expanded to
a, aa, aaa, and aaaa before trash could execute. Those four parameters 
were then passed
on to the mv command in my script. However, trash passes only the first 
parameter to the
mv command, ignoring the remaining parameters. Fortunately, they weren't 
removed, but
the script still didn't achieve what I wanted.
You can actually have up to nine parameters, named $1 to $9. However, 
our goal is to catch
all parameters, regardless of the amount. To do that, we use $@:
mv $@ ~/.trash/
Make that change to your script, then test it by removing multiple 
files. You should now
have a script that works every time.
1.9.5 Taking Out the Trash
You should occasionally go through your trash directory and really 
remove the files you no
longer want. If you're really on your toes you may be thinking, "But how 
do I empty the
trash directory?" If you do this:
% rm ~/.trash/*
your trash directory won't lose any files! This time you really do want 
to use rm, not trash.
To tell your shell to use the real rm command, simply put a \ in front 
of it like so:
% \rm /trash/*
Voila, empty recycling bin.
One obvious extension is to keep versioned backups. Use the date command 
to find the
time of deletion and append that to the name of the file in the trash 
command. You could
get infinitely more complicated by storing a limited number of versions 
or deleting all
versions older than a week or a month. Of course, you could also keep 
your important files
under version control and leave the complexity to someone else!

Karel Miklav wrote:
> Xu Qiang wrote:
> 
>>... is the lack of a cyclin bin, from which you can restore anything
>>you have mis-deleted before.
>>
>>Or, am I mis-informed on this issue?
> 
> 
> I scratched my head about it too and finally wrote a simple script
> which moves trashed items into auto made date-stamped directories. I
> can send it later, if there's interest.
> 

-- 
Best regards,

Peter

http://AboutSupport.com



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?42E5E0A1.7010600>