#!/usr/bin/perl
######################################################################## count files and directories (mwx'2016)
use Getopt::Std;getopts('dnh');

$version='1.0.2';

if ($opt_h) {;&help;exit;}

if (-d $ARGV[0]) {
  &dx($ARGV[0]);
} else {
  &dx(".");
}

sub dx() {
  my($dir)=@_;
  $ml=length($dir);

  opendir(DIR,$dir);
  while($f=readdir(DIR)) {
    if ($f ne '.' && $f ne '..') {
    
      if (-d "$dir/$f") {
        $n=0;$s=0;
        open(IN,"find '$dir/$f' -type f |");
        while(<IN>) {
          chomp();
          $s+=(stat($_))[7];
          $ts+=(stat($_))[7];
          $n++;
          $tn++;
        }
        close(IN);
        $N{"$f/"}=$n;
        $S{"$f/"}=$s;
        $ml=length($f) if (length($f)>$ml);  
      }
            
      if (-f "$dir/$f" && !$opt_d) {
        $S{$f}+=(stat("$dir/$f"))[7];
        $ts+=(stat("$dir/$f"))[7];
        $N{$f}++;
        $tn++;
        $ml=length($f) if (length($f)>$ml);          
      }
            
    }
  }
  closedir(DIR);

  $frm=sprintf "%%-%ds",$ml+1;
  $out=sprintf "$frm   %8d %8s\n",$dir,$tn,&formsize($ts);

  if ($opt_n) {
    for $f (sort { $N{$a} <=> $N{$b} } (keys(%N))) {
      $out.=sprintf "  $frm %8d %8s\n",$f,$N{$f},&formsize($S{$f});
    } 
  } else {
    for $f (sort { $S{$a} <=> $S{$b} } (keys(%S))) {
      $out.=sprintf "  $frm %8d %8s\n",$f,$N{$f},&formsize($S{$f});
    }  
  }
  print $out;
}

####################################################################################################### SUPPORT

sub formsize() {
  my($b)=@_;
  if ($b>1024*1024*1024*1024) {
    $s=sprintf("%.0fT",$b/1024/1024/1024/1024)
  } elsif ($b>1024*1024*1024) {
    $s=sprintf("%.0fG",$b/1024/1024/1024)
  } elsif ($b>1024*1024) {
    $s=sprintf("%.0fM",$b/1024/1024)
  } elsif ($b>1024) {
    $s=sprintf("%.0fK",$b/1024)
  } else {
    $s=sprintf("%.0f",$b)
  }
  return $s;
}

sub help() {
print <<"ENDOFHELP";
dx ${version}, count files and directories, mwx'2016
usage: dx [-n] [-d] [path]
  -n  sort by number of files (default by size)
  -d  count only directories
  -h  this help
ENDOFHELP
}

########################################################################################################### END

