Path: utzoo!attcan!uunet!husc6!bloom-beacon!apple!bionet!agate!helios.ee.lbl.gov!nosc!ucsd!ucsdhub!hp-sdd!hplabs!hpda!hpdslab!hpiacla!marki From: marki@hpiacla.HP.COM (Mark Ikemoto) Newsgroups: comp.unix.questions Subject: Re: Creating a nondestructive 'rm' Message-ID: <3600014@hpiacla.HP.COM> Date: 6 Nov 88 04:46:51 GMT References: <4460006@hpindda.HP.COM> Organization: HP Indus. Appl. Center, Sunnyvale, CA Lines: 324 Try this. It runs a little too slow for me but maybe you're running on a faster machine. ( Matt, for the b_on, b_off, u_on, u_off script variables, you'll need to replace with the real escape character so the bolding will work on your HP terminal. I deliberately used so other people's non-HP terminals accessing Notes wouldn't get screwed up by the escape chars when they looked at this script. ) Mark ------------ CUT LINE: Remove this line and everything above it ------------ # Bourne shell script ####################################################################### # # @(#) TITLE: Safer rm command # # # DESCRIPTION: See user man page below. # # INSTALLATION: # # Save this to a file. Change user-defined shell vars after the # script header to your taste and terminal. Set the permissions on # this script to 'execute'. Invoke this script with no parameters # to see the embedded man page. # # UPDATE HISTORY: # # what date/who type of change # ---- -------- -------------- # 01/18/88 # Mark Ikemoto >Script created. # # 03/03/88 # Mark Ikemoto >Added touch command to give file the current time # so it isn't cleaned up until it is older than the # system backup timestamp file. # # @(#) 11/05/88 # Mark Ikemoto >Added much more comments. # >Added pseudo support for the -f option. # >Isolated HP terminal escape chars into shell vars. # ####################################################################### # Shell user-defined functions # #################################################################### # Start of main commands # #------------------------------------------------------------------- # USER MUST SET THESE VARIABLES FOR INSTALLATION OF THIS SCRIPT # USER MUST SET THESE VARIABLES FOR INSTALLATION OF THIS SCRIPT # USER MUST SET THESE VARIABLES FOR INSTALLATION OF THIS SCRIPT # junkdirname="$HOME/.rmfiles" # name of user junk file subdir rmlogfile="rmlogfile" # list of removed files # bolding/underlining for error messages and for keywords in the # man page... b_on='&dB' # set bolding on for HP terminal b_off='&d@' # set bolding off for HP terminal u_on='&dD' # set underlining on for HP terminal u_off='&d@' # set underlining off for HP terminal # For other types of terminals, substitute appropo # terminal char sequences or just set b_on, b_off, # u_on, u_off to empty (''). #------------------------------------------------------------------- # Initialize some global vars # PATH=/bin:/usr/bin:/usr/contrib/bin:/usr/local/bin:/etc:. TZ=PST8PDT; export TZ # set time zone for invocations of cmds like date, etc. options= export options fname=`basename $0` cap_fname=`echo $fname | tr "[a-z]" "[A-Z]"` # make filename uppercase cmdline=$* # used in help-checking later on # default settings: overwrite='false' # force overwriting; don't prompt for user verify? interactive='false' # user wants to verify copy for each source file? removedir='false' # user wants to remove a subdir? default = no. #------------------------------------------------------------------- # Set up some traps for signals. NOTE that any shell variables used # in the trap routine must have been defined previous to this trap # declaration. # trap "echo $cap_fname: Type $fname -h\ for help.'; exit 2" \ 1 2 3 6 7 15 #------------------------------------------------------------------- # Grab args from command line # set -- `getopt ifrh $*` # check if a valid command line entered if [ $? -ne 0 ] then echo "$b_on $cap_fname: Bad runstring option.$b_off" echo "$b_on Type $fname -h for help.$b_off " exit 2 fi #------------------------------------------------------------------- # Parse command args # help_wanted=false while [ $# -gt 0 ] do case $1 in -i) interactive='true';; -f) ;; -r) removedir='true';; -h) help_wanted='true';; --) shift; break;; # end of options in command line; # source/target names should remain in runstring *) echo "$b_on $cap_fname: Bad runstring option.$b_off " echo "$b_on Type $fname -h for help.$b_off " exit 2;; esac shift done #------------------------------------------------------------------- # Does user want a help screen? # if [ -z "$cmdline" -o "$help_wanted" = 'true' ] then more <] ... $b_off $b_on $fname -h$b_off $b_on DESCRIPTION$b_off A safer rm command. Will "delete" files/subdirs and move them to a user "junk file" subdirectory. The current junk dir name being used is $b_on $junkdirname $b_off . This junk dir name is hardcoded into this script. This script assumes that the junk dir already exists before calling this script. The $u_on arguments$u_off are: $b_on <-i>$b_off will cause $fname to obtain authorization from the user before removing each source file. $b_on <-f>$b_off does absolutely nothing and is only accepted for compatibility with the real rm's runstring options. $b_on <-r>$b_off will cause $fname to remove the subdir specified in the runstring. The subdir tree structure is moved to the junk file subdir intact before the source subdir is removed. $b_on ...$b_off are the names of the files/dirs to delete. $b_on -h$b_off will cause this help screen to be displayed. This is the same as typing $fname with no parameters. Files deleted can be unremoved by the user; the unremoval must be done by hand (sorry). This is because the user might have removed several files with the same name and the user would have to go into each file anyway to figure out which is the file that they want to unremove. When a file/dir is moved to the junk directory, it is renamed with a unique filename so that future rm'ing of files with the same name will not cause files in the junk directory to be overwritten. However, if all of the removed files in the junk directory have unique, non-user-friendly names, then the user will have a heck of a time trying to figure out which file is the one they want if they want to restore a file. So, before files are renamed during the remove process, their original name and their new unique name will be placed as an entry in a listing file, $b_on $junkdirname/$rmlogfile $b_off , along with a prefix, 'f' or 'd', to indicate whether the entry is a removed file or directory, respectively. Note that once a file/dir has been unremoved, its entry in the listing file still exists. The user must remove their entry from this listing by hand (sorry again). $b_on WARNING$b_off This script is not portable because of the use of HP terminal escape sequences in the man page and error messages. You must alter script shell vars to make this portable. $b_on AUTHOR$b_off HP R&D Lab. ! exit 0 fi # #---------------------------------------------------------------------- # Do the main loop while [ $# -gt 0 ] do if [ "$interactive" = 'true' ] then echo "Remove $1? (y/n/a[bort]) \c" read answer if [ "$answer" = 'a' ] then exit 0 fi if [ "$answer" != 'y' -a "$answer" != 'Y' ] then shift # go on to next source file name continue fi fi if [ -d "$1" ] then if [ $removedir != 'true' ] then echo "$b_on $cap_fname: Specified directory removal of $1$b_off " echo "$b_on but remove-dir option (-r) not specified.$b_off " echo "$b_on Type $fname -h for help.$b_off " shift continue # bypass this name; go to the next one fi # create a subdir inside the junk file subdir in which to # deposit "removed" subdir file(s) # rmname="`expr substr $LOGNAME 1 4``date +%m%d%H%M%S`" mkdir $junkdirname/$rmname touch "$junkdirname/$rmname" # give file the current time to aid in # cleaning up the junk dir using this timestamp cp -r $1 $junkdirname/$rmname /bin/rm -r $1 echo "d $1 $rmname" >> $junkdirname/$rmlogfile else rmname="`expr substr $LOGNAME 1 4``date +%m%d%H%M%S`" /bin/mv $1 "$junkdirname/$rmname" touch "$junkdirname/$rmname" # give file the current time to aid in # cleaning up the junk dir using this timestamp if [ $? != 0 ] then echo "$b_on $cap_fname: Cannot access file/subdir $1 .$b_off " echo "$b_on Consult man pages or$b_off " echo "$b_on type $fname -h for help.$b_off " exit 1 fi echo "f $1 $rmname" >> $junkdirname/$rmlogfile fi shift done exit 0 # removal complete ####################################################################### # IMPLEMENTATION NOTES/ENHANCEMENT REMINDERS: # # 1. I was giving some consideration into making this a C program so that # it would run faster. Currently, it is too slow for my tastes. # # Note that one problem in making this thing run faster would be in # timestamping the files uniquely, especially if you are copying/renaming # several short files all at the same time. The system clock would # not have enough opportunity to change to a unique set of digits. # # 2. Instead of uniquely identifying duplicately-named removed files via # timestamping in the filename, how about keeping the names the same # as the originals as much as possible but adding number suffixes if # removing duplicately-named files. This eliminates the need for # an rmlogfile to map timestamped names to real names. # # 3. We give the removed files the current mod timestamp so the files' # mod timestamp could be used by some sort of cleanup script to do # periodic cleanup of the junk dir. Maybe the cleanup script could # be run during login. # # 4. If I had more time, I could develop an 'unrm' command script that, # when invoked with the name of the file/dir to unremove, would # look in the removed-file listing and display all entries matching # the user-specified filename. We could provide unique sequence # numbers for each entry, so that the user, after seeing the display # of candidate entries, could specify the index number of the # entry to unremove. # # This script would remove the entry from the listing after # after completion of the removal of the file/dir itself. # # The other problem that must be overcome is that even if we display # the candidate list entries to the user for unremoval, the user still # may not be able to tell which file is which if there are several # entries with the same original file name. The fix for this would # be to allow the user during rm'ing to specify a comment to be added # to the list file entry for that file. When the user asks to # unremove a file and is shown the list entries of possible candidates, # the user will also see the comment field for each entry. #