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

Hi,

I am new to perl scripting and wrote a perl script to read the directories and files and count the no of files in each directory and generate a log file. The problem is it is not printing anything to the log file. I am copying the script below.

!/usr/local/bin/perl $dir= 'c:\My Projects\Perl Scripts\New Folder' ; $directory_count = 0; $file_count=0; $outfile = 'log.txt'; open OUTF, "> $outfile" or die print " can't create logfile; $!"; for $dir ( @dirs ) { opendir( DIR, "$dir" ) ; @files = readdir( DIR ) ; foreach $file ( @files ) { if ( -f "$dir/$file") { $directory_count++; } else { $file_count++; } } { print "Directories: $directory_count\n"; print "Files: $file_count\n"; } closedir( $dir ) ; } close OUTF ; exit 0;

Replies are listed 'Best First'.
Re: Perl Script to count files and directories is not working.
by psini (Deacon) on Aug 26, 2010 at 18:37 UTC

    First of all, use strictures (use strict; use warnings;)! This could show you some of the errors.

    You first initialize a scalar $dir with a path but then overwrite it with for $dir ( @dirs ) { extracting from an undefined array @dirs.

    you open and close OUTF, but then you print to stdout, so your output go to the shell and not to the log file.

    Update: I didn't notice you are a new user; welcome to the Monastery!

    Rule One: "Do not act incautiously when confronting a little bald wrinkly smiling man."

    A reply falls below the community's threshold of quality. You may see it by logging in.
Re: Perl Script to count files and directories is not working.
by TomDLux (Vicar) on Aug 26, 2010 at 18:51 UTC

    A short program is just a long program that isn't finished yet. Always use use warnings;. Always use use strict;.

    Do that now, and see what progress you achieve.

    Once you get past declaring $dir, $directory_count, $file_count and $outfile, you will discover that your for-loop is iterating over and undefined array, @dirs. Since @dirs is empty, you never enter the loop, so no print statements.

    No, we can't re-write it for you, do your own homework.

    As Occam said: Entia non sunt multiplicanda praeter necessitatem.

      Hi, Thanks for the reply. I declared strict and warnings and came to know my errors. In process of correcting them.
Re: Perl Script to count files and directories is not working.
by toolic (Bishop) on Aug 26, 2010 at 23:37 UTC
    The read_dir function from File::Slurp is also handy for getting a listing of directory entries. It filters out the special 'dot' directories by default.

    Also, perltidy is handy for indenting your code.

    use strict; use warnings; use File::Slurp; my @dirs = ('./'); my $directory_count = 0; my $file_count = 0; my $outfile = 'log.txt'; open my $fh, '>', $outfile or die "can't create logfile; $!"; for my $dir (@dirs) { for my $file (read_dir($dir)) { if ( -f "$dir/$file" ) { $directory_count++; } else { $file_count++; } } print $fh "Directories: $directory_count\n"; print $fh "Files: $file_count\n"; } close $fh;
      Hi, Thank a lot. Learned new things as i am new to perl.
Re: Perl Script to count files and directories is not working.
by kejohm (Hermit) on Aug 27, 2010 at 10:16 UTC

    You could also look at the File::Find module for traversing directories. Here is your code rewritten using File::Find:

    #!perl use strict; use warnings; use File::Find; my $dir = 'c:/My Projects/Perl Scripts/New Folder'; my $directory_count = 0; my $file_count = 0; my $outfile = 'log.txt'; find( sub { # $_ contains the name of the current file # $File::Find::name contains the full path of the current file + relative # to the directory given to the find() function # $File::Find::dir contains the name of the current directory if(-d $_){ # if file is a directory $directory_count++; } elsif(-f $_) { # else if file is a plain file $file_count++; } }, $dir ); open my $log, q(>), $outfile or die "Can't create logfile; $!"; print {$log} "Directories: $directory_count\n"; print {$log} "Files: $file_count\n"; close $log;

    Here are a few things regarding the code that you submitted:

    • The directory that you specified to search looks like a Windows path, but you have a Unix path in the shebang line. The shebang line isn't necessary on Windows, except that Perl may look here for switches, such as -w.
    • You need to use the -d operator to test for a directory. The -f operator tests whether the file is a plain file.
    • It is preferable nowadays to use a variable as a reference to a filehandle, rather than using a bareword; since a bareword is global, it may clobber an existing filehandle.
    • The code open OUTF, "> $outfile" or die print " can't create logfile; $!"; doesn't do what you might think. If the file can't be opened, the print function will execute, printing the message, which will return a true value, which die will use as its message. So you might get output something like this:
      1 at script.pl line 10. Can't create logfile; Access is denied.
      The arguments passed to die() will be printed to STDERR for you, so you needn't bother with print().
    • The final exit 0; isn't that necessary in Perl, unless you want to explicitly return a value from your script.
    • toolic mentioned perltidy above for properly formatting your code. There is another tool called Perl::Critic which you can use to apply various coding standards to your code. It is an excellent module for learning some good coding practices and you can easily modify it to match your own personal coding preferences.

    Update: Links fixed.

      Hi, Thank you for the reply. Checked on my errors and its working.
Re: Perl Script to count files and directories is not working.
by pemungkah (Priest) on Aug 29, 2010 at 00:41 UTC
    As just a note - try to get into the habit of indenting. It will help a lot to make your code easier to read (and to find mis-nested blocks when you get further along).

    Perl::Tidy can help clean up your code automatically.