getsizes.pl (du -chs with sorted results..)

#!/usr/bin/perl
# note:  change the path to perl to match your system.  This script also requires
# File::Find
#
# getsizes.pl, or getsizes
# Prints out a total size for a file or directory or a
# list of sizes sorted with the largest at the end of a
# given set of files/directories.
#
# YES, I KNOW THAT: 
#     "du -hcs" and/or "du -sch * |sort -n; du -sch" and/or 
#     "du -sc * |sort -n ; du -csh" 
# (for 'total report always at the end, last one sorts correctly but won't show 
# human-readable summaries for dirs) will do this already, but the version of du on 
# the generals (ASU's general unix cluster) won't 'du' the -h flag, and I rather 
# had spent a little time making a script to break down sizes in human-readable 
# format than having to do the math every single time I wanted to know... :).  
#
# UPDATE:  Added a 'total size' report when more than one argument is passed. 
# Also cleaned up and added 'TB' sized conditional check.
# example: getsizes ./ prints "1234.04MB : ./
#          getsizes * would print
#                                 "23KB : file.txt
#                                  1.2004MB :  small_dir
#                                  44.45546MB : not_as_small_dir
#                                  2.0045GB : fat_dir_that_needs_trimming_down"
#                                  TOTAL SIZE: xxx.xxxyy
#
#             Note: If you actually get similar results as the above on the generals,
#                 please do tell me how to get 2GB of space on AFS without breaking any
#             rules :-) 
#
#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 2 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program; if not, write to the Free Software
#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#    (for a copy of the GPL license,  point your browser to

use File::Find;

my $totalsize = 0;
my %sizes;
my $arc = @ARGV;

&getHash(@ARGV);
&printSortList;

sub getHash {
    @list = @_;
    foreach $item (@list) { if (!($d =~ /^\-w$/)) {
                ($size) = &getsize($item);
            chomp $size;
            $totalsize += $size;
            $sizes{"$size"} = $item;
        }
    }
}

sub printSortList {
    # numerically sort the list entries by size before printing out to screen... 
    @keys = (keys %sizes);
    my $c = 0;
    my @newkeys = ();
    # needed because simply calling sort() sorts alphanumerically
    foreach my $k (sort { $a <=> $b } @keys) {
        $newkeys[$c] = $k;
        $c += 1;
    }

    foreach $value (@newkeys) {
        $entry = $sizes{$value};
        &printReadable($entry,$value);
    }
    if ($arc > 1) {
        &printReadable("TOTAL SIZE",$totalsize);
    }
}

sub getsize  {
    ($Gentry) = @_;
    $Gsize = 0;
    find sub { $Gsize += -s }, ($Gentry);
    return ($Gsize);
}

sub printReadable {
    ($Oentry, $Osize) = @_;
    $ext = "B"; 

    if ($Osize > 1024) {
        $Osize = ($Osize / 1024);
        $ext = "KB";
        if ($Osize > 1024) {
            $Osize = ($Osize / 1024);
            $ext = "MB";
            if ($Osize > 1024) {
                $Osize = ($Osize / 1024);
                $ext = "GB";
                if ($Osize > 1024) {
                    $Osize = ($Osize / 1024);
                    $ext = "TB";
                }
            }
        }
    }
    $Osize = sprintf("%.4f", $Osize);
    print "$Osize$ext : $Oentry\n";
}