Find number of sub directories within a directory

R

rishid

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

ioneabu

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;
}
 
R

rishid

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 }; }
}
 
J

John W. Krahn

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
 
J

Jay Tilton

: 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;
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,816
Latest member
SapanaCarpetStudio

Latest Threads

Top