#!/bin/ksh
# @(#) bigfiles.ksh 1.1 93/08/02
# 93/04/13 john h. dubois iii (john@armory.com)
# 93/06/15 Added -d and -v options, fixed sorting so it works with -n,
#          changed xargs command to avoid running l -d w/o args
# 93/08/02 Added -b, -s, and -i options.

alias istrue="test 0 -ne"
alias isfalse="test 0 -eq"

name=${0##*/}
comp_exts="z,Z,gz,arc,zip,zoo,gif"
bin_exts="exe,lib,com,ovl,obj,bin,sys,o,a"
typeset -i days=0 defK=4 verbose=0
Usage=\
"Usage: $name [-abhnsv] [-i<file>] [-k<size>] [-eE<exts>] [-d<days>] [dir ..]"
cut_cmd="cut -c 34-"
sort_cmd="sort +4 -5 -n -r"
grep_cmd=cat

while getopts :ahnvsbk:e:E:d:i: opt; do
    case $opt in
    a)
	comp_exts=
	;;
    h) echo \
"$name: find large uncompressed files and list them sorted by size.
$Usage
Files larger than ${defK}K that do not have any of the following extensions
are listed:" {$comp_exts} "
Options:
-h: Print this help.
-n: Print filenames only.  By default, file size, date, and name are printed.
-e <ext[,ext...]>: Do not list files with any of the given extensions.
   The given list replaces the internal list.  Extensions should be
   separated by commas and should not be preceded by a '.'; the preceding
   '.' is included internally.
-E <ext[,ext...]>: Like -e, except that the given extensions are added to
   the internal list instead of replacing it.
-b: Add the following binary file extensions to the default list of ignored
   extensions:" {$bin_exts} "
-i <file>: Ignore the files whose names are given in <file>.
   The filenames must be given with the same path as $name would print.
-a: List all big files regardless of extension.
-d <days>: List only files that have not been accessed in at least <days> days.
   This changes the default for <size> to 0; that is, all files at least <days>
   old will be listed, regardless of size.  The size can still be set with -k.
-k <size>: List only files larger than <size> kilobytes.
-s: Sort by filename instead of size.
-v: Print the command issued to find files."
       exit 0;;
    n)
	cut_cmd="awk '{ print \$9; }'"
	shift
	;;
    k) 
	typeset -i K=$OPTARG || exit 1
	;;
    d) 
	days=$OPTARG || exit 1
	defK=0
	;;
    v)
	verbose=1
	;;
    e) 
	comp_exts=$OPTARG
	;;
    E) 
	comp_exts="$comp_exts,$OPTARG"
	;;
    b)
	comp_exts="$comp_exts,$bin_exts"
	;;
    s)
	sort_cmd="sort +8"
	;;
    i)
	grep_cmd="fgrep -xvf $OPTARG"
	;;
    +?) 
	echo "$name: options should not be preceded by a '+'."
	exit 1
	;;
    ?) 
	echo "$name: $OPTARG: bad option.  Use -h for help."
	exit 1
	;;
    esac
done
 
[ -z "$K" ] && typeset -i K=$defK

# remove args that were options
let OPTIND=OPTIND-1
shift $OPTIND

[ $# -eq 0 ] && set -- .

set +o noglob

ExtPred=
if [ -n "$comp_exts" ]; then
    ExtPred='( '`eval echo "-name \*."{$comp_exts}" -o"`' -name "" )'
fi

set -o noglob

# Use val & +val instead of +(val-1) so that they will work if val is 0,
# w/o having to remove expression for special case 0.
for dir
do
    istrue verbose && echo \
    find "$dir" -size +$K \( -atime $days -o -atime +$days \)\
    \( -mtime $days -o -mtime +$days \) ! $ExtPred -print

    find "$dir" -size +$K \( -atime $days -o -atime +$days \)\
    \( -mtime $days -o -mtime +$days \) ! $ExtPred -print |
    $grep_cmd | 
    ( xargs sh -c '[ $# -gt 0 ] && l -d "$@"' ) |
    $sort_cmd |
    eval $cut_cmd
done
