f



Find number of sub directories within a directory

Hi,

Objective of program is: get total file size in a folder, get total
recursive file size (including all subdirectories and the directory
itself) and get number of sub directories in each directory.

Example---
Want output to be something like this, I can format the output don't
worry about that, just need to get the information into the hash or
whereever.
Dir       File Size     Recursive File Size       # of Sub dirs
c:\blah       100kb         400kb                     4
c:\blah\f1    50kb           50kb                     0
c:\blah\f2    50kb           50kb                     0
c:\blah\f3    50kb           50kb                     0
c:\blah\f4    150kb          150kb                    0

I have got the total file size in a directory to work, but cannot seem
to get the recursive file size and subpaths.  Should be a quick few
modifications to do the code, but cannot figure it out. (Still need to
learn hashes better)

Thanks for any help,

Here is my code:
#!/usr/bin/perl -w
use strict;
use File::Find;
use File::Spec;
use Data::Dumper;

my $size_key = "SIZE%:/_-SIZE";
my $file_key = "FILE%:/_-FILE";
my $subdir_key = "SUBDIR%:/_-SUBDIR";

my $root_dir = ".";              # Default.  Change as needed.
my $dir_tree = {};

find(\&wanted, $root_dir);

#print "Dir <./foo> is ",
$dir_tree->{"."}{"foo"}{$size_key},"blocks.\n";

#print Dumper $dir_tree;

sub wanted
{
  my $size = (stat $_)[7];
  my @path_components = File::Spec->splitdir($File::Find::name);

  my $filename = pop @path_components;

  my $pointer = $dir_tree;
  foreach my $component (@path_components)
  {
    #$filename = $File::Spec->catdir($pointer, $component);
    $pointer = $pointer->{$component};
    $pointer->{$size_key} += $size;
  }
  if (-d $_)
  {
    # add a new hash component.
    $pointer->{$_} = { $size_key => $size };

    # add 1 to subdir key to each parent directory
    my $dir = $File::Find::dir;
    #print "$_\t$dir\n";
    $pointer->{$dir} = { $subdir_key => 0 };
    my @dir = split (/\//, $dir);
    foreach my $var (@dir) {
      print "$var\n";
      #$pointer->{$subdir_key} += 1;
    }    
  }
  else {	  
    	  $pointer->{$file_key} += 1;	  
  }
}

0
rishid (34)
5/11/2005 2:39:41 PM
comp.lang.perl.misc 33233 articles. 2 followers. brian (1246) is leader. Post Follow

4 Replies
578 Views

Similar Articles

[PageSpeed] 18

rishid@gmail.com wrote:
> Hi,
>
> Objective of program is: get total file size in a folder, get total
> recursive file size (including all subdirectories and the directory
> itself) and get number of sub directories in each directory.
>
> Example---
> Want output to be something like this, I can format the output don't
> worry about that, just need to get the information into the hash or
> whereever.
> Dir       File Size     Recursive File Size       # of Sub dirs
> c:\blah       100kb         400kb                     4
> c:\blah\f1    50kb           50kb                     0
> c:\blah\f2    50kb           50kb                     0
> c:\blah\f3    50kb           50kb                     0
> c:\blah\f4    150kb          150kb                    0
>
> I have got the total file size in a directory to work, but cannot
seem
> to get the recursive file size and subpaths.  Should be a quick few
> modifications to do the code, but cannot figure it out. (Still need
to
> learn hashes better)
>
> Thanks for any help,
>
> Here is my code:
> #!/usr/bin/perl -w
> use strict;
> use File::Find;
> use File::Spec;
> use Data::Dumper;
>
> my $size_key = "SIZE%:/_-SIZE";
> my $file_key = "FILE%:/_-FILE";
> my $subdir_key = "SUBDIR%:/_-SUBDIR";
>
> my $root_dir = ".";              # Default.  Change as needed.
> my $dir_tree = {};
>
> find(\&wanted, $root_dir);
>
> #print "Dir <./foo> is ",
> $dir_tree->{"."}{"foo"}{$size_key},"blocks.\n";
>
> #print Dumper $dir_tree;
>
> sub wanted
> {
>   my $size = (stat $_)[7];
>   my @path_components = File::Spec->splitdir($File::Find::name);
>
>   my $filename = pop @path_components;
>
>   my $pointer = $dir_tree;
>   foreach my $component (@path_components)
>   {
>     #$filename = $File::Spec->catdir($pointer, $component);
>     $pointer = $pointer->{$component};
>     $pointer->{$size_key} += $size;
>   }
>   if (-d $_)
>   {
>     # add a new hash component.
>     $pointer->{$_} = { $size_key => $size };
>
>     # add 1 to subdir key to each parent directory
>     my $dir = $File::Find::dir;
>     #print "$_\t$dir\n";
>     $pointer->{$dir} = { $subdir_key => 0 };
>     my @dir = split (/\//, $dir);
>     foreach my $var (@dir) {
>       print "$var\n";
>       #$pointer->{$subdir_key} += 1;
>     }
>   }
>   else {
>     	  $pointer->{$file_key} += 1;
>   }
> }

I can't totally figure out your solution.  It looks too complicated and
un-perlish.  Here's my attempt.  It runs.

#!/usr/bin/perl

use strict;
use warnings;
use File::Find;

my $size;
total();

sub total
{
        find(\&wanted1, $ARGV[0]);
}
sub subtotal
{
        $size = 0;
        find(\&wanted2, shift);
}
sub wanted1
{
        if (-d)
        {
                subtotal($_);
                print "$File::Find::name is this big: $size\n";
        }
}
sub wanted2
{
        $size += -s;
}

0
ioneabu
5/11/2005 4:53:20 PM
I actually figured it out (:   Understand hashes and why you use
references now.  Here is the code if anyone cares.

Thanks for the help

#!/usr/bin/perl -w
use strict;
use File::Find;
use File::Spec;
use Data::Dumper;

my $size_key = "SIZE%:/_-SIZE";
my $recsize_key = "AGGSIZE%:/_-AGGSIZE";
my $file_key = "FILE%:/_-FILE";
my $recfile_key = "AGGFILE%:/_-AGGFILE";
my $subdir_key = "SUBDIR%:/_-SUBDIR";

my $root_dir = ".";              # Default.  Change as needed.
my $dir_tree = {};   # Reference to an empty hash

find(\&wanted, $root_dir);

#print "Dir <./foo> is ",
$dir_tree->{"."}{"foo"}{$size_key},"blocks.\n";

print Dumper $dir_tree;

sub wanted
{
	my $size = (stat $_)[7];
	my @path_components = File::Spec->splitdir($File::Find::name);

	my $filename = pop @path_components;

	my $pointer = $dir_tree;

	# add a new hash component.
	foreach my $component (@path_components)
	{
		# Add size to each directory until it reaches last directory
		$pointer->{$recsize_key} += $size;
		# If directory, add to number of subdirectories, else add 1 to
recursive files
	    	if (-d $_) {
			$pointer->{$subdir_key} += 1;
		}
	    	else {
			$pointer->{$recfile_key} += 1;
		}
	    	# Move pointer to next directory and add size
	    	$pointer = $pointer->{$component};
	    	$pointer->{$size_key} += $size;
	}
	
	if (-d $_) { $pointer->{$_} = { $size_key => $size }; }
}

0
rishid
5/11/2005 5:54:16 PM
rishid@gmail.com wrote:
> 
> Objective of program is: get total file size in a folder, get total
> recursive file size (including all subdirectories and the directory
> itself) and get number of sub directories in each directory.
> 
> Example---
> Want output to be something like this, I can format the output don't
> worry about that, just need to get the information into the hash or
> whereever.
> Dir       File Size     Recursive File Size       # of Sub dirs
> c:\blah       100kb         400kb                     4
> c:\blah\f1    50kb           50kb                     0
> c:\blah\f2    50kb           50kb                     0
> c:\blah\f3    50kb           50kb                     0
> c:\blah\f4    150kb          150kb                    0
> 
> I have got the total file size in a directory to work, but cannot seem
> to get the recursive file size and subpaths.  Should be a quick few
> modifications to do the code, but cannot figure it out. (Still need to
> learn hashes better)
> 
> Thanks for any help,
> 
> Here is my code:
> #!/usr/bin/perl -w
> use strict;
> use File::Find;
> use File::Spec;
> use Data::Dumper;
> 
> my $size_key = "SIZE%:/_-SIZE";
> my $file_key = "FILE%:/_-FILE";
> my $subdir_key = "SUBDIR%:/_-SUBDIR";
> 
> my $root_dir = ".";              # Default.  Change as needed.
> my $dir_tree = {};
> 
> find(\&wanted, $root_dir);
> 
> #print "Dir <./foo> is ",
> $dir_tree->{"."}{"foo"}{$size_key},"blocks.\n";
> 
> #print Dumper $dir_tree;
> 
> sub wanted
> {
>   my $size = (stat $_)[7];
>   my @path_components = File::Spec->splitdir($File::Find::name);
> 
>   my $filename = pop @path_components;
> 
>   my $pointer = $dir_tree;
>   foreach my $component (@path_components)
>   {
>     #$filename = $File::Spec->catdir($pointer, $component);
>     $pointer = $pointer->{$component};
>     $pointer->{$size_key} += $size;
>   }
>   if (-d $_)
>   {
>     # add a new hash component.
>     $pointer->{$_} = { $size_key => $size };
> 
>     # add 1 to subdir key to each parent directory
>     my $dir = $File::Find::dir;
>     #print "$_\t$dir\n";
>     $pointer->{$dir} = { $subdir_key => 0 };
>     my @dir = split (/\//, $dir);
>     foreach my $var (@dir) {
>       print "$var\n";
>       #$pointer->{$subdir_key} += 1;
>     }    
>   }
>   else {	  
>     	  $pointer->{$file_key} += 1;	  
>   }
> }
> 

This looks like it does what you want:

#!/usr/bin/perl
use warnings;
use strict;

use File::Spec::Functions qw(splitdir catdir);
use File::Find;
use Data::Dumper;

my $root_dir = '.';
my %data;

find( sub {
     return if /^\.\.?$/;
     stat;
     if ( -d _ ) {
         $data{ $File::Find::dir }{ subs }++
         }
     else {
         $data{ $File::Find::dir }{ size } += -s _;
         my @dirs = splitdir( $File::Find::dir );
         do  {
             $data{ catdir( @dirs ) }{ total } += -s _;
             } while pop @dirs;
         }
     }, $root_dir );

print Dumper \%data;

__END__



John
-- 
use Perl;
program
fulfillment
0
John
5/11/2005 9:35:31 PM
"rishid@gmail.com" <rishid@gmail.com> wrote:

: Objective of program is: get total file size in a folder, get total
: recursive file size (including all subdirectories and the directory
: itself) and get number of sub directories in each directory.
: 
: Example---
: Want output to be something like this, I can format the output don't
: worry about that, just need to get the information into the hash or
: whereever.
: Dir       File Size     Recursive File Size       # of Sub dirs
: c:\blah       100kb         400kb                     4
: c:\blah\f1    50kb           50kb                     0
: c:\blah\f2    50kb           50kb                     0
: c:\blah\f3    50kb           50kb                     0
: c:\blah\f4    150kb          150kb                    0
: 
: I have got the total file size in a directory to work, but cannot seem
: to get the recursive file size and subpaths.  Should be a quick few
: modifications to do the code, but cannot figure it out. (Still need to
: learn hashes better)

[snip code]

You're evidently working on a Windows platform.  Access to much of the
information you seek is built into the Windows Script Host, which is
Perl-accessible through Win32::OLE.

    #!perl
    use warnings;
    use strict;
    use Win32::OLE qw( in );
    use List::Util qw( sum );
    use Text::Table;

    my $tb = Text::Table ->new(
        "Dir", \'|',
        "File Size", \'|',
        "Recursive File Size", \'|',
        "# of Sub dirs"
    );

    my $fso = Win32::OLE ->new('Scripting.FileSystemObject');
    dir_size( $fso ->GetFolder( 'c:\temp' ) );
    print $tb;

    sub dir_size {
        my($dir) = @_;
        my $files = $dir ->Files;
        my $subdirs = $dir ->Subfolders;
        $tb ->add(
            $dir ->Path,
            sum( map $_ ->Size, in $files),
            $dir ->Size,
            $subdirs ->Count
        );
        dir_size($_) for in $subdirs;
    }

0
tiltonj
5/12/2005 1:51:35 AM
Reply: