[comp.sources.misc] v07i014: scavenge.ksh: clean up old files in /tmp

allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc) (06/04/89)

Posting-number: Volume 7, Issue 14
Submitted-by: naz@hslrswi.UUCP (Norman H. Azadian)
Archive-name: scavenge.ksh

Here is a tool I use on my PC running under the MKS Toolkit.
This shell script could presumably be adapted quite simply to run
under any unix, although the need for it would be less on a real unix.

[You think.  Of course, most people on the Usenet are intelligent enough
not to install applications in /tmp; the people *I* have to hand-hold aren't.
Cleaning up /tmp is a real project on *their* systems.  ++bsa]

Being the cautious type, I generally put unwanted files in /tmp.  Later,
when I need disk space, I run this tool to actually delete the oldest
of those files.  It also knows enough to look in other places where I
keep old, expendable, files.

As a cautious type, I've built in all manner of safeguards and options
to allow me to see what's going to be deleted, and to give me a veto.
The basic operation of the tool, however, is quite simple.  When
invoked with no argument, it reports the number of KBytes which
could be recovered by deleting old files.  When invoked with a number,
it will delete just enough old files to increase the available disk
space by that many KBytes.

The -L option allows you to review the list of termination candidates,
using the pager named in your PAGER environment variable.  Failing
such a variable, it will use a default.  I currently have the default
set to my own hacked version of less.  A more reasonable choice for
most people would be the pg.exe program that comes with the toolkit.

BUG NOTE:  It is supposed to delete the files in chronological order.
In my version 2.2d of the Toolkit, the -t option of ls does not
work correctly, and so files are not deleted in chronological order.
If you have a newer version, it might work for you.

#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	scavenge.ksh
# This archive created: Thu May 25 14:28:15 1989
# By:	Norman H. Azadian (Hasler AG)
export PATH; PATH=/bin:$PATH
echo shar: extracting "'scavenge.ksh'" '(5625 characters)'
if test -f 'scavenge.ksh'
then
	echo shar: will not over-write existing file "'scavenge.ksh'"
else
cat << \SHAR_EOF > 'scavenge.ksh'
#	/usr/bin/scavenge.ksh	890523	NHA
# With no parameters, simply reports the number of KBytes in expendable files.
# With 1 parameter, prepares a list of temporary files to delete such that
#  that number of KBytes will be freed up on the disk.
# The -Fspec option allows the user to prepend filespecs to fileSpec.
# The -I option makes the selection process Interactive.
# The -L option shows the list of files that can/will be deleted.
# The -V option makes all output verbose.
# Exit status is always 0 for success, otherwise 1.
# At present only the last filespec suggested by the user will be processed.

# Files are selected for deletion in line with the following priorities:
#   1) minimize the number of directories (filespecs) affected.
#   2) maximize the age of the files deleted.
##NOTE THAT IN VERSION 2.2D OF THE TOOLKIT, THE -T OPTION OF LS IS BROKEN.
##THEREFORE THE ORDER OF DELETION MIGHT NOT BE OPTIMAL.


# User-definable constants
##typeset defaultPager='pg'
##typeset defaultPrompt='-p__h_for_help,___q_to_continue_______________Page_%d'
typeset defaultPager='less -aVh_for_help,___v_to_edit,___q_to_continue'
typeset defaultPrompt='-aVh_for_help,___v_to_edit,___q_to_continue'
#filespecs must be put in an array, one spec per array element.
typeset fileSpec
fileSpec[1]='/tmp/*'
fileSpec[2]='/file[0-9][0-9][0-9][0-9].chk'
fileSpec[3]='/usr/obsolete/*'


# Internal constants and variables
typeset -i blocksPerKByte=2					#2 blocks per KByte
typeset -i Vopt=0 Iopt=0 Lopt=0				# -V and -I and -L option flags
typeset masterList=/tmp/__scav__.tmp		#master list of gleanable files
typeset tmpFile=/tmp/__temp__.tmp			#temporary file
typeset usrFileSpec=" "						#user filespec gets stashed here


#parse command line
typeset -i requested=0
for arg
do
	case $arg in
		-[iI])	Iopt=1
				;;
		-[vV])	Vopt=1
				;;
		-[fF]*)	usrFileSpec=${arg#-[fF]}
				;;
		-[lL]*)	Lopt=1
				;;
		[0-9]*)	requested=$arg
				;;
		*)		cat <<-\FOOBIE_BLETCH
				scavenge -- free up disk space by deleting temporary files
				usage:  scavenge  [-Fspec]  [-I]  [-L]  [-V]   [kbytes]
				-Fspec	spec is pre-pended to list of expendable filespecs
				-I      Interactive file selection
				-L      List of eligible files is shown
				-V      Verbose outputs
				kbytes  number of KBytes to recover.  default 0

				If  kbytes  is not given, nothing will be deleted.
				FOOBIE_BLETCH
				exit 1
				;;
	esac
done
##echo "Iopt=$Iopt   Lopt=$Lopt   Vopt=$Vopt   requested=$requested"


#initialize master listing file
if test   $Lopt -ne 0   -a   $Vopt -ne 0
then
	echo 'BLKS PERMISSION LNK BYTES  DATE  TIME  FILENAME'  >$masterList
	echo '==== ========== == ====== ====== ===== ========================================' >>$masterList
else
	rm  -f  $masterList
fi


#Draw up the master list of candidates.
#	"If one day it should happen that a victim must be found,"
#	"I've got a little list..."     -- Lord High Executioner from "The Mikado"
# first the user-suggested filespec
if test -r  `echo $usrFileSpec | cut -d" " -f1`
then
	#build sorted list  |  remove "total" line  |  remove directories
	ls.exe -trlsd $usrFileSpec  |  egrep -v '^total [0-9]+'  | \
										egrep '^[\ 0-9]+\ \-'  >>$masterList
fi
# then all the built-in filespecs
typeset -i i=1
while (( i < ${#fileSpec[*]} ))
do
	if test -r  `echo ${fileSpec[i]} | cut -d" " -f1`
	then
		#build sorted list  |  remove "total" line  |  remove directories
		ls.exe -trlsd ${fileSpec[i]}  |  egrep -v '^total [0-9]+'  |  \
										egrep '^[\ 0-9]+\ \-'  >>$masterList
	fi
	let i=i+1
done


#Handle the -L option
if test $Lopt -ne 0
then
	if test -z "$PAGER"
	then
		$defaultPager  $defaultPrompt   $masterList
	else
		$PAGER  $masterList
	fi
	if test $Vopt -ne 0
	then										#get rid of header lines
		tail +2 $masterList  >$tmpFile
		mv  $tmpFile  $masterList
	fi
fi
	

typeset blocks permissions links       month     timeYear name reply
typeset -R8 bytes
typeset -R2 day
typeset -i neededBlocks neededKB


#Handle case where only a report is wanted.
if ((requested == 0))
then
	while read -r blocks permissions links bytes month day timeYear name
	do
		((neededBlocks = neededBlocks + blocks))
	done <$masterList
	((neededKB = neededBlocks / blocksPerKByte))
	if ((Vopt == 0))
	then
		echo $neededKB
	else
		echo "$neededKB KBytes are eligible for scavenging."
	fi
	exit 0
fi


#bail out if there's nothing available
if test ! -s $masterList
then
	if test $Vopt -ne 0
	then
		echo "scavenge: no files to scavenge."
	fi
	exit 1
fi


#Now for the delicate task of deciding who gets the axe.
neededBlocks=`expr $requested '*' $blocksPerKByte`
while test $neededBlocks -gt 0
do
	while read -r blocks permissions links bytes month day timeYear name
	do
		if test $Iopt -ne 0
		then
			if test $Vopt -ne 0
			then
				echo "Delete $bytes $month $day $timeYear $name\t[Nyq] ? \c"
			else
				echo "$name\t[Nyq] ? \c"
			fi
			reply=`line` </dev/con
			reply=${reply:=No}				#empty line means "No"
		else
			reply=Yes
		fi
		if test -z "${reply##[qQ]*}"
		then
			break;							#bail out
		fi
		if test -z "${reply##[yY]*}"
		then
			((neededBlocks = neededBlocks - blocks))
			if test $Vopt -ne 0
			then
				let 'neededKB = neededBlocks / blocksPerKByte'
				echo "deleting $name -- $neededKB KBytes to go"
			fi
			rm $name
			if test $neededBlocks -le 0
			then
				break
			fi
		fi
	done <$masterList

	if test $Vopt -ne 0   -a   $neededBlocks -gt 0
	then
		neededKB=`expr $neededBlocks '/' $blocksPerKByte`
		echo "scavenge: still need to eliminate $neededKB KBytes"
		echo "scavenge: hit carriage return to continue, ^C to quit"
		line
	else
		exit 0
	fi
done
SHAR_EOF
if test 5625 -ne "`wc -c < 'scavenge.ksh'`"
then
	echo shar: error transmitting "'scavenge.ksh'" '(should have been 5625 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0

NHA
===
PAPER:  Norman Azadian; Hasler AG; Belpstrasse 23; 3000 Berne 14; Switzerland
X.400:  naz@hslrswi.hasler
UUCP:   ...{uunet,ukc,mcvax,...}!cernvax!hslrswi!azadian
VOICE:  +41 31 63 2178            BITNET: naz%hslrswi.UUCP@cernvax.BITNET