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

Hi, I wanted to iterate trough a series of directories inside a main directory and then do other other work inside each file of each direcotry. I'm trying like this with no luck
#!/usr/bin/perl use strict; use warnings; use Text::CSV; my $dir = "C:/Users/ST/DesktopSample"; opendir (my $gdh, $dir) or die "Unable to open main directory"; my @dirs = grep {-d} readdir($gdh); closedir($gdh); foreach my $tumordirs (@dirs) { #opendir (my $tdh, $tumordirs) or die "Unable to open subdir"; print "$tumordirs\n"; }
If i print the name of the directories with the print i get . ..

Replies are listed 'Best First'.
Re: Iterate trough a series of folders
by kennethk (Abbot) on Apr 04, 2016 at 17:42 UTC
    The problem you are having is that readdir returns the directory contents without path information. You probably want to change that to
    my @dirs = grep {-d "$dir/$_"} readdir($gdh);
    or even better
    my @dirs = grep {/[^.]/ and -d "$dir/$_"} readdir($gdh);
    and
    opendir (my $tdh, "$dir/$tumordirs") or die "Unable to open subdir";
    or alternately change your working directory with chdir. You might also simplify your life by using File::Find.

    #11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.

      Thank you very much for your advice sir, it works, but i'm struggling understanding why yours works and mine not. By the way, your help is much appreciated.
        Using "$dir/$_" changes your paths from relative to absolute. Unless your working directory (the directory your shell was in when you executed perl) is equal to $dir, -d will be looking in the wrong place. This might be more obvious if you execute the code:
        #!/usr/bin/perl use strict; use warnings; use 5.10.0; my $dir = "C:/Users/ST/DesktopSample"; opendir (my $gdh, $dir) or die "Unable to open main directory"; say for readdir($gdh); closedir($gdh);

        #11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.

Re: Iterate trough a series of folders
by 1nickt (Canon) on Apr 04, 2016 at 18:56 UTC

    You can use Path::Tiny for this:

    #!/usr/bin/perl use strict; use warnings; use Path::Tiny qw/ path /; my $dir = "C:/Users/ST/DesktopSample"; my $iterator = path( $dir )->iterator({ recurse => 1, follow_symlinks => 0, }); while ( my $path = $iterator->() ) { if ( path( $path )->is_dir ) { ... } if ( path( $path )->is_file ) { ... } }
    The iterator will automatically skip . and ..

    Hope this helps!


    The way forward always starts with a minimal test.
Re: Iterate trough a series of folders
by Laurent_R (Canon) on Apr 04, 2016 at 18:56 UTC
    You might want to use the glob function, which simplifies significantly what you are trying to do: it preserves the path of the files and removes the . and .. pseudo directories.
    my @dirs = grep {-d} glob ("$path/*");
Re: Iterate trough a series of folders
by Marshall (Canon) on Apr 04, 2016 at 18:13 UTC
    readdir will return the directories without complete path. the "." and ".." are also returned just like if you did ls or dir under windows. "." is current dir, and ".." is previous directory. You need to filter those out. grep {!/^./ and -d $_}readdir; if you have "hidden directories that start with "." and you want them, then modify grep accordingly.
Re: Iterate trough a series of folders
by FreeBeerReekingMonk (Deacon) on Apr 04, 2016 at 18:25 UTC
    I am unsure this works in Windows (as it probably uses the shell expansion), but try this:
    @tumorfiles = sort <C:/Users/ST/DesktopSample/*/*>;

    Where that * can be as complex as <C:/Users/ST/DesktopSample/TUMOR-*/*.dat>

      I confirm that this works even on windows (but only with / as path separator: see File::Glob notes).

      i must admit i never used this construct (but directly glob ). it is described in the IO operators

      perl -E "say for sort <./*/*.pm>" | grep -c . 4

      See also Re: Searching for specific text for more examples and the difference between iterative and recursive solutions.

      L*

      There are no rules, there are no thumbs..
      Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.