Creating a nondestructive 'rm'
James Logan III
logan at vsedev.VSE.COM
Sun Nov 6 15:43:31 AEST 1988
In article <4460006 at hpindda.HP.COM> burdick at hpindda.HP.COM (Matt Burdick)
writes:
>Does anyone have a nice alias or shell script so that when I 'rm' a file it
>will actually move it to, for instance, a tmp subdirectory in my home
>directory?
Yes, I do. I just wrote it last week and have not thouroughly
tested it, but as far as I can tell, it works fine. My version
COPIES each file, rather than moving it so that it can be used
across partitions. Unfortunately, you must have read access to
the file in order to remove it with this script. If you don't
have read access, just use /bin/rm or move the file manually.
Basically, rm() copies each file you want removed to a directory
called "trash" in your $HOME directory. If you want this trash
directory to be called something else, just set the environment
variable "TRASH" to the full pathname of the directory.
When invoked with the -r option, rm() will copy every file under
the specified directory and remove the directory. Each file is
copied to $TRASH, but the original hierarchy is not retained so
be careful when you remove two files with the same name in
different sub-directories!
The -i flag works pretty much like the real rm.
Once a month I usually use the "discard" function to remove all
of these files with /bin/rm for real. It will prompt you for
permission to delete each file unless you use the -f option.
One problem with discard() is that I forgot to make it remove
invisible files that have filenames beginning with ".".
(Sorry that I haven't written a man page for these yet -- I just
haven't gotten around to it... If there is any interest I will
post the man pages sometime next week or so...)
I define these functions in a file called ".kshrc" in my home
directory and set the ksh's ENV variable so that these functions
will be read by each sub-shell.
I wrote these functions to be portable between the Bourne shell
and the Korn shell. Just send me email if you want details on
using these functions in Bourne shell-script form...
I used only variable names that start with an underscore so that
they would not interfere with any other scripts. Also, I unset
the variables I use in rm() since the option flags stay permanently
set otherwise.
If you find any bugs or can think of any enhancements, just send
me email.
-Jim
-------------------------------------------------------------------------------
hastrash() {
# Written by James Logan (vsedev!logan) 11/88
# Check existence of $TRASH
if test -z "$TRASH"; then
TRASH=$HOME/trash;
fi;
if test ! -d "$TRASH"; then
echo >&2 "$0: Making trash directory $TRASH...\c";
if mkdir "$TRASH"; then
echo >&2 "done.";
else
echo >&2 "\n$0: Cannot make directory $TRASH";
return 1;
fi;
fi;
if test ! -w "$TRASH"; then
echo >&2 "$0: Cannot write in $TRASH.";
return 1;
fi;
return 0;
}
rm() {
# Written by James Logan (vsedev!logan) 11/88
# Take out this next line when you are sure that /bin/rm is
# not being called by mistake.
echo >&2 "(rm() function)";
unset _ARG _RECURSIVE _NOERROR _INTERACTIVE _COMMAND _FILE _RESP;
hastrash || return 1;
if test $# = 0; then
echo >&2 "usage: $0 [-rfi] file ...";
return 1;
fi;
set -- `getopt "rfi" $*`;
for _ARG in $*; do
case "$_ARG" in
-r)
_RECURSIVE=1;
;;
-f)
_NOERROR=1;
;;
-i)
_INTERACTIVE=1;
;;
--)
shift;
break;
;;
esac;
shift;
done;
if test "$_RECURSIVE"; then
_COMMAND="find $* -type f -print";
else
_COMMAND="for _I in $*; do echo \$_I; done;";
fi;
eval $_COMMAND |
while read _FILE; do
if test "$_INTERACTIVE"; then
echo "$_FILE? ";
read _RESP </dev/tty;
case "$_RESP" in
[Yy]*)
;;
*)
continue;
;;
esac;
fi;
if test ! -f "$_FILE"; then
echo >&2 "$0: $_FILE: not a file";
continue;
fi;
if cp $_FILE $TRASH; then
/bin/rm $_FILE;
else
return 1;
fi;
done;
if test "$_RECURSIVE"; then
/bin/rmdir $*;
fi;
return 0;
}
discard() {
# Written by James Logan (vsedev!logan) 11/88
# Take out the trash
hastrash || return 1;
case $# in
0)
;;
1)
if test "$1" = "-f"; then
_FORCE="1";
else
echo >&2 "Usage: $0 [ -f ]";
return 1;
fi;
;;
*)
echo >&2 "Usage: $0 [ -f ]";
return 1;
;;
esac;
if test "$_FORCE"; then
/bin/rm -f $TRASH/*;
return $?;
fi;
for _FILE in $TRASH/*; do
echo "$_FILE? [y, n, q]:\c";
read _RESPONSE;
case "$_RESPONSE" in
[qQ]*)
return 0;
;;
[yY]*)
/bin/rm -f $_FILE;
;;
[nN]*)
continue;
;;
esac;
done;
return 0;
}
-------------------------------------------------------------------------------
--
Jim Logan logan at vsedev.vse.com
(703) 892-0002 uucp: ..!uunet!vsedev!logan
inet: logan%vsedev.vse.com at uunet.uu.net
More information about the Comp.unix.questions
mailing list