begood321 has asked for the wisdom of the Perl Monks concerning the following question:

use strict; use warnings; use diagnostics; use Cwd; # module for finding the current working directory my @root = ( ### Workareas ### #"Y:\\default\\main\\test.com\\WORKAREA\\www\\managed-assets\\www\\sma +rtphones\\test-one-v\\all-round-view", "C:\\Users\\Ben\\Documents\\test\\", #"U:\\default\\main\\WORKAREA\\", ); ### just to make sure the file is emptied before we start my $output_file = qq|C:\\Users\\Ben\\Documents\\test\\tools\\count_res +ults.txt|; my $output_file2 = qq|C:\\Users\\Ben\\Documents\\test\\tools\\dirs_sea +rched.txt|; open(MYFILE, ">$output_file") || die "opening $output_file: $!"; # ov +erwrite my $dir = ""; my $cmd = "C:\\Perl\\bin\\perl -le \"print scalar localtime\""; my $date = `$cmd`; my $count; my @final_count; my @files; foreach(@root) { &write_file("$date"); print "\nScanning : $_\n\n"; &ScanDirectory($_); } close(MYFILE); ############################################### # ScanDirectory ############################################### sub ScanDirectory { my ($path) = shift; my($startdir) = &cwd; # keep track of where we began chdir($path) or die "Unable to enter dir $path:$!\n"; opendir(DIR, ".") or die "Unable to open $path:$!\n"; my @names = readdir(DIR); closedir(DIR); my $count = 0; # LOOP RECURSIVELY foreach my $name (@names){ ### skipped next if ($name eq "."); next if ($name eq ".."); #next if ($name =~ m/.*\.\w+/); ### Skip symlink #next if(-l $name); ### Check to see if directory if (-d $name){ next if($name !~ m|(^[a-zA-Z0-9])|); print qq|\nScanning dir $startdir/$path/$name ...|; @files = <$startdir/$path/$name/*>; $count = @files; &write_file2("Scanning dir $startdir/$path/$name ...\n"); &ScanDirectory($name); next; } } print qq|\nTotal file count: $count|; chdir($startdir) or die "Unable to change to dir $startdir:$!\n"; } ###################################################################### +### # padZero pads single digit dates and time with a leading zero. ###################################################################### +### sub write_file { my $str = shift; open(MYFILE, ">>$output_file") || die "opening $output_file: $!"; + # append print MYFILE $str; close(MYFILE); } # end write_file sub write_file2 { my $str2 = shift; open(MYFILE2, ">>$output_file2") || die "opening $output_file2: $! +"; # append print MYFILE2 $str2; close(MYFILE2); } # end write_file

Not counting all files in directories. It appears glob has limitations to some files

@files = <$startdir/$path/$name/*>; $count = @files;

I'm trying to see if I can find solution to get all files to be counted

I also tried another foreach loop which will work for 1 directory but have difficulty printing dir then count in next line as it does now recursively.

Replies are listed 'Best First'.
Re: Count files in directories
by Anonymous Monk on Apr 01, 2012 at 00:56 UTC

    ??????? my $date = localtime;

    my $cmd = "C:\\Perl\\bin\\perl -le \"print scalar localtime\""; my $date = `$cmd`;

    use my $date = localtime;

    The problem with glob is that it globs with all the bash-iness that entails (white space as seperator, etc, etc )

    A good alternative is File::Find::Rule

Re: Count files in directories
by Marshall (Canon) on Apr 01, 2012 at 19:25 UTC
    You are doing a lot of work that can be done with the core File::Find module.

    File::Find recurses down a directory tree from a list of starting points. When File::Find enters a directory, it does a readdir(). The output of that can be processed by a user supplied subroutine - could say prune off paths not to follow or sort the names or whatever. Here I just counted the number of simple files (-f) and returned the list of files/directories unchanged.

    The wanted() subroutine will be called for each file/directory - but I don't think there is anything to be done in this example, so it does nothing.

    #!/usr/bin/perl -w use strict; use File::Find; # a core module (no installation needed) # my @root= ("C:/temp"); #an array of starting directories my %options = (preprocess =>\&new_dir, wanted=>\&wanted); my $date = localtime; $date =~ s/\b(\d)\b/0$1/g; #pad single digits with zero #this seemed to be a requirement for some #reason print "$date\n"; find ( \%options, @root); sub new_dir { my @files = @_; # the readdir() output # contains both (files and directories) my $num_files = grep{-f}@files; #-f are simple files printf "%-5i %s\n", $num_files, $File::Find::dir; return @files; #return the list to continue processing } sub wanted { # not used here, but dummy sub is needed for syntax # this routine is called for each file/directory # if we wanted to do something special for each one # maybe get a size or whatever... # the full path name of this file would be in $File::Find::name } __END__ Sun Apr 01 12:18:32 2012 1278 C:/temp 8 C:/temp/dbdcsv 4 C:/temp/dictionary 2 C:/temp/inline 1 C:/temp/inline/_Inline ... blah ...
Re: Count files in directories
by dasgar (Priest) on Apr 01, 2012 at 20:59 UTC

    Since it looks like you're wanting to get the file count of a directory on a Windows system, you might want to check out Win32::DirSize. Basically you call Win32::DirSize's dir_size function and pass in the path of the directory and FileCount is one of the keys of the returned hash.

    Of course, if you're trying learn how to do this on your own or need something that will work on non-Windows platforms, then Win32::DirSize may not be the best choice to go with.