du -dirs

Eric Thelin eric@thelin.org
Fri, 23 Jun 2000 19:14:02 -0700 (MST)


On Fri, 23 Jun 2000, Kevin Buettner wrote:

> On Jun 23,  5:57pm, Eric Thelin wrote:
> 
> > Ah, but the shell script will count the files in the whole tree from the
> > starting directory down.  But the perl version will only count files in
> > the directory itself.  So for most uses the shell script is better.  So
> > newbies would be better off using the shell script.  Of course this
> > leaves a challenge for the perl hackers to fix\b\b\bimprove the perl
> > version.  OK, so I am writing this because I want the perl script to be
> > as good as the shell one but I am too lazy to do it myself :)
> 
> Ummm... I think you'd better try it.  Both scripts have identical
> functionality.

I didn't make myself clear.  I was referring to the shell line that uses
"find" and not perl at all.  The two you wrote will definitely yield the
same results because they are the same code just running through two
different interfaces.

I ran your code on a few different directories and compared it with the
find based output and it was the same on ext2 partitions.  But on my smbfs
mounted drive that I was checking on it was not descending past the
called directory???  This would seem to be an issue in the File::Find
module.  So I have made yet another version.  See below.

> 
> I've tested it on my /usr/local hierarchy and got identical results:
> 
> ocotillo:ptests$ ./fsizes2.pl /usr/local
> 107029246
> ocotillo:ptests$ ./fsizes2.sh /usr/local
> 107029246
> 
> > On Thu, 22 Jun 2000, Kevin Buettner wrote:
> > 
> > > On Jun 22,  1:29am, Kevin Buettner wrote:
> > > 
> > > > Below another way to do it that doesn't use perl.
> > > [...]
> > > > find $1 -type f -not -type l -printf '%s\n' | awk -- '{s += $0} END {print s}'

This find above works on all partition types.


I hacked up another version that is longer but doesn't use File::Find
and so it works on windows partitions too.  But it is even longer than
the first one. :(


--- fsizes3.pl ---
#!/usr/bin/perl -w

use File::Find;

die "Usage $0 root-dir(s)\n" unless defined $ARGV[0];

while($arg=shift @ARGV)
{
  print "$arg\t".dirsize($arg,10)."\n";
}

sub dirsize
{
  my($dir,$max_depth,$file,$filepath,$s);
  local *DIR;
  ($dir,$max_depth)=@_;
  $s=0;
  return(0) if ($max_depth==0);
  opendir(DIR,$dir);
  while(defined($file=readdir(DIR)))
  {
    next if $file =~/^\.\.?$/;
    $filepath=$dir."/".$file;
    if(-f $filepath && !-l $filepath)
      {$s+=-s $filepath;}
    elsif(-d $filepath)
      {$s+=dirsize($filepath,$max_depth-1);}
  }
  closedir(DIR);
  $s;
}