#! /usr/bin/env wish8.4

proc generate.list dir {
 set l [list]

 foreach f [glob -nocomplain [file join $dir *]] {
  if {[file isdirectory $f]} {
   set l [concat $l [generate.list $f]]
  } elseif {[file exists $f]} {
   lappend l [list [file size $f] $f]
  }
 }
 return $l
}

proc main {argc argv} {

 switch -- $argc {
  0 {
   set dir [pwd]
  }

  1 {
   set dir [lindex $argv 0]
  }

  default {
   syntax
   return 1
  }
 }

 set l [generate.list [file normalize $dir]]

 #This next segment uses:
 # pow(2,10) for a Kilobyte = 1024
 # pow(2,20) for a Megabyte = 1048576
 # pow(2,30) for a Gigabyte = 1073741824

 foreach finfo [lsort -dictionary -decreasing -index 0 $l] {
  set type B

  foreach {size f} $finfo {
   if {$size >= 1073741824} {
    set type GB
    set size [expr {$size / 1073741824.0}]
   } elseif {$size >= 1048576} {
    set type MB
    set size [expr {$size / 1048576.0}]
   } elseif {$size >= 1024} {
    set type KB
    set size [expr {$size / 1024.0}]
   } 

   if {[set i [string first . $size]] >= 0} {
    set size [string range $size 0 [expr {$i + 2}]]
   }
   puts [format {%+10.10s %-2.2s %s} $size $type $f]
  }
 }
 return 0
}
exit [main $::argc $::argv]