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

Hi, I am new to perl. Infact just 2 days old. I am trying to make a script to list recursively the files in the directories. The problem is very simple but i still can't get what is the problem. Right now i have written only these lines:
$dirname = "C:/Perl/Test"; opendir(DIR,$dirname); @file1 = readdir(DIR); foreach $file1(@file1) { if (-f $file1) { print("$file1\n"); } }
but the if condition is not working and its returning nothing in the output. However if i remove the if, it is printing the list of all files and directories. Can anybody tell what is the problem in it?

Replies are listed 'Best First'.
Re: Why is "If" condition not working
by davido (Cardinal) on Jul 03, 2011 at 06:04 UTC

    If you look in the documentation for readdir you will see:

    If you're planning to filetest the return values out of a readdir, you'd better prepend the directory in question. Otherwise, because we didn't chdir there, it would have been testing the wrong file.

    So if you change your code as follows, it will work:

    $dirname = "C:/Perl/Test/"; opendir(DIR,$dirname); @file1 = readdir(DIR); foreach $file1(@file1) { if (-f "$dirname$file1") { print("$file1\n"); } }

    Since you're new to Perl, it's the perfect time to learn how to program with 'use strict' in mind. Try this:

    use strict; use warnings; use autodie; my $dirname = "C:/Perl/Test/"; opendir my( $dir_handle ), $dirname; my @file1 = readdir $dir_handle; foreach my $file1 ( @file1 ) { if ( -f "$dirname$file1" ) { print "$file1\n"; } }

    This is a good time to introduce grep, which can make looping tests that result in a list much simpler.

    use feature qw/ say /; use strict; use warnings; use autodie; my $dirname = "C:/Perl/Test/"; opendir my( $dir_handle ), $dirname; my @files = grep { -f "$dirname$_" } readdir $dir_handle; say for @files;

    say is a feature of Perl starting with 5.10. It basically just adds a "\n" to every call. my is explained best in perlsub.


    Dave

Re: Why is "If" condition not working
by GrandFather (Saint) on Jul 03, 2011 at 06:07 UTC

    readdir returns the a directory entry, not a full path. You need to do something like:

    if (-f "$dirname\\$file1") {

    Note that it is a bad idea to overload variable names. Your sample code uses file1 as both an array name and as the name of a scalar variable - bad, bad bad! Also, if you find yourself tacking a number on the end of a variable name then you probably want to be using an array instead, but that may be a different lesson.

    True laziness is hard work
Re: Why is "If" condition not working
by Marshall (Canon) on Jul 03, 2011 at 13:01 UTC
    I am trying to make a script to list recursively the files in the directories.

    There is a module File::Find which is handy for doing recursive searches of a directory tree. See File::Find. File::Find starts at the directory that you specify and for every directory and file found, it calls a subroutine that you specify. Below this is just called "wanted". There are some special variable names that apply while you are inside the wanted subroutine as shown below.

    #!/usr/bin/perl -w use strict; use File::Find; # within the wanted subroutine: # # http://perldoc.perl.org/File/Find.html # $File::Find::dir is the current directory name, # $_ is the current filename within that directory # $File::Find::name is the complete pathname to the file. my @directories_to_search = ('C:/temp'); find(\&wanted, @directories_to_search); sub wanted { print "$File::Find::name\n" if -f; }
Re: Why is "If" condition not working
by bart (Canon) on Jul 03, 2011 at 19:27 UTC
    -f $file1, with $file1 the basename of a file (as returned by readdir), can only return true if a file with that name exists in the current directory.

    Your current directory is not the directory that you opened for scanning with readdir. That's why it (usually) returns false. If it returns true, it's because, by incident, a different with the same name exists in your current directory.