#!/bin/bash # # lss - reformated 'ls' sorted by size, possibly with pager # # Rev 00 01/07/97 From mydir. # Rev 01 01/29/97 Use 'bash' instead of 'ksh'. # Rev 02 11/24/03 Better handling of names with embedded spaces. # Rev 03 04/28/04 Change output format; put size first; output totals # ###### Here are some development notes: # # It works to suppress error messages from 'ls' as in the following: # # COUNT=`ls -ad1 $LSARG 2>/dev/null |wc -l` # # it also works to compare $COUNT to $# (with some additional logic) # in order to see if the operator entered a bad filename, but we'll # just pass any error messages from 'ls' on to the operator. # ###### # # I've spent two days unsuccessfully trying to learn how to avoid the # use of a temporary file in this script, focusing mainly on trying to # use a shell variable to pass the various parameters to 'ls'. This # met with varying degrees of success, but the part that never worked # properly had to do with filenames containing spaces. The properties # of the special parameters $@, "$@", $*, and "$*" always seemed to get # screwed up when I tried to use these parameters from within another # shell variable. # ### ### Set chars/line and lines/page for pager use decision ### CPLINE=79 PGLIMIT=23 TMPFILE1=$(mktemp /tmp/lss.XXXXXX) if [ $? -ne 0 ] ; then TMPFILE1=/tmp/lss.1.tmp fi TMPFILE2=$(mktemp /tmp/lss.XXXXXX) if [ $? -ne 0 ] ; then TMPFILE2=/tmp/lss.2.tmp fi if [ $# -eq 1 ] ; then if [ -d "$1" ] ; then cd $1 ls -alFS --full-time >$TMPFILE1 else ls -alFS --full-time "$1" >$TMPFILE1 fi elif [ $# -eq 0 ] ; then ls -alFS --full-time >$TMPFILE1 else # we just any error messages on stderr go through to the user ls -alFS --full-time "$@" >$TMPFILE1 fi COUNT=$(cat $TMPFILE1 |wc -l) if [ $COUNT -lt 1 ] ; then rm -f $TMPFILE1 rm -f $TMPFILE2 exit 1 fi gawk -v cpline=$CPLINE -v pglimit=$PGLIMIT ' \ BEGIN { total_size = 0; total_items = 0; line_count = 0; } { # # supress the 'total' line # if ($1 == "total") next; # # find the filename part of the line # s = $0; for (i=1;i<11;i++) { j = index(s,$i) + length($i); s = substr(s,j); } j = index(s,$11) s = substr(s,j); # # if this is a symlink, find the LAST " -> " string in the filename part. # if (substr($1,1,1) == "l") { i = 1; j = 0; i = index(substr(s,i)," -> "); while (i) { j = i; i = i + 3; i = index(substr(s,i)," -> "); } if (j) { # substitute a '@' character for the " -> target" part. s = substr(s, 1, j-1) "@"; } } s = sprintf ("%7s %s%s%s %s\n", $5, $8, $7, substr($10, 3), s); printf "%s", s; total_size += (0 + $5); total_items++; line_count += int((length(s)+cpline-1)/cpline); } END { # Print totals in a pleasing format. # # first, pretty up the total item count. # s1 = total_items ""; t1 = ""; n = length(s1); while (n > 3) { t1 = "," substr(s2,n-2) t1; n = n - 3; s1 = substr(s1,1,n); } if (n > 0) t1 = s1 t1; # # next, pretty up the total byte count. # s2 = total_size ""; t2 = ""; n = length(s2); while (n > 3) { t2 = "," substr(s2,n-2) t2; n = n - 3; s2 = substr(s2,1,n); } if (n > 0) t2 = s2 t2; # # compute the output line # s = t1 " entries using " t2 " bytes" # # finally, display it # n = length(s); for (i=0;i pglimit) exit 1; else exit 0; } ' $TMPFILE1 >$TMPFILE2 if [ $? -eq 1 ] ; then cat $TMPFILE2 |less else cat $TMPFILE2 fi rm -f $TMPFILE1 rm -f $TMPFILE2 exit 0