http://www.perlmonks.org?node_id=168869

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

Wise Elders, I am but a serf on the monastery.. Wine pressing available by request. When I read a directory contents into an array, and test the elements to find directories, it does not return directory values unless the path I am reading from is the local (.) directory. WhatUp with that? If I remove the test, the correct contents are returned, the test just seems to fail.
#!/usr/bin/perl $path="."; opendir (DIR, $path) or die "could not open directory"; @files = readdir(DIR); foreach (@files) { print "$_ \n" if (-d $_) ; }


updated by boo_radley :title change

Replies are listed 'Best First'.
Re: Dumb or Cursed?
by ides (Deacon) on May 23, 2002 at 18:59 UTC
    When using file test operators like -d you need to give it the full path to the file. You might try for instance
    print "$_\n" if ( -d "$path/$_" );

    -----------------------------------
    Frank Wiles <frank@wiles.org>
    http://frank.wiles.org

re : Problems with -filetest on readdir results
by boo_radley (Parson) on May 23, 2002 at 19:01 UTC
    readdir doesn't prepend the path information, you need to do it yourself.
    something like :
    print "$_ \n" if (-d $path.$_);
    should do you. This assumes that $path has the appropriate directory separator on the end.
Re: Problems with -d filetest on readdir results
by cjf (Parson) on May 23, 2002 at 19:07 UTC

    You need to provide -d with the $path ...

    #!/usr/bin/perl -w use strict; my $path = "/usr/bin"; opendir DIR, $path or die "Couldn't read directory: $!"; my @directories = grep { -d "$path/$_" } readdir DIR; closedir DIR; foreach (@directories) { print $_, "\n"; }

    Update: Changed $path to "$path/$_" so it prints out only the directories (as opposed to all the files). Thanks to ChemBoy for spotting this and providing the fix.

Re: Dumb or Cursed?
by choocroot (Friar) on May 23, 2002 at 19:07 UTC
    The files you get from readdir are relative to your directory $path and -d test for files from the current directory.
    So, you need to specify your path in the test :
    use strict; my $path = "/usr/local/"; opendir( DIR, $path ) or die "could not open dir : $!\n"; my @files = readdir( DIR ); foreach my $file (@files) { print "$file\n" if( -d "$path/$file" ); }
Problems with -filetest on readdir results
by atopolc (Pilgrim) on May 24, 2002 at 03:11 UTC
    This is a great opportunity to use map especially if you are going to need the path again later in your script. From your code Untested:
    #!/usr/bin/perl $path="."; opendir (DIR, $path) or die "could not open directory"; @files = map {"$path/$_"}, readdir(DIR); #maps the path into your arra +y foreach (@files) { print "$_ \n" if (-d $_) ; }
    Update: Thanks merlyn
Re: Dumb or Cursed?
by BazB (Priest) on May 23, 2002 at 18:59 UTC

    #!/usr/bin/perl use strict; use warnings; my $path="/foo/bar/"; opendir (DIR, $path) or die "Could not open directory: $!"; @files = readdir(DIR); foreach my $file (@files) { print "$file\n"; }
    Your foreach loop was incorrect. Use of strict and warnings also helps spot errors.
    You could also replace the foreach loop with a map statement:
    print map {$_ = "$_\n";} @files;
    Cheers!

    BazB.

    Update: I ignored the -d test, and obviously don't know my foreach loop from my elbow. Oops. ides++ and boo_radley++