in reply to How to get sub-folder names using perl?

Hello erhan,

There are two problems with your code. The first is that it fails to distinguish between directories and files within the foreach loop. I assume your script resides in /home/abc/Desktop/test, in which case the call to readdir will return the name of the script (and the names of any other files in this directory) along with the subdirectory names. Then within the loop the call to chdir($subdir) will fail. As james28909 has shown, this is easily fixed by putting:

next if -f $subdir;

as the first statement within the loop, although I would prefer:

next unless -d $subdir;

The second problem is that the statement chdir(".."); at the end of the loop fails to return the current working directory to the correct location, so on a subsequent iteration chdir($subdir) is called with the value a, but there is no directory named a within the current working directory. A simple solution is to reset the current working directory at the start of each loop iteration:

foreach my $subdir ( sort @subdirs ) { chdir($dir); next unless -d $subdir; ...

Here is my preferred version:

use strict; use warnings; use Cwd; use File::Path qw( make_path ); my $dir = cwd(); opendir(my $dh, $dir) or die "Unable to open directory '$dir': $!" +; my @subdirs = readdir $dh or die "Unable to read directory '$dir': $!" +; closedir $dh or die "Unable to close directory '$dir': $! +"; my $result_path = $dir . '/results'; make_path $result_path; chdir $dir; for my $subdir (sort @subdirs) { chdir $dir; next unless -d $subdir; my $newdir = $result_path . '/' . $subdir; make_path $newdir; chdir $dir . '/' . $subdir; system("echo '1 0' | program -f methane.trr -o $result_path/$subdi +r/outfile.txt"); }

Hope that helps,

Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

Replies are listed 'Best First'.
Re^2: How to get sub-folder names using perl?
by erhan (Novice) on Mar 08, 2015 at 06:05 UTC
    @Athanasius, thanks for your reply. Your code works. Sorry. But I didn't understand its some parts:
    my $result_path = $dir . '/results';
    where, why did you use point . there?
    next unless -d
    Also I didn't understand what this part does.
    chdir $dir . '/' . $subdir;
    And this . '/' . part? Thanks in advance,

      Hello erhan,

      (1) In Perl there are two ways to concatenate strings:

      1. The dot operator: see perlop#Additive-Operators
      2. Double-quote interpolation: see perlop#Quote-and-Quote-like-Operators

      In the present case, my $result_path = $dir . '/results'; has the same effect as my $result_path = "$dir/results";, so the choice between them is merely stylistic. But as a general rule, it’s best to avoid double-quote interpolation if you don’t need it: see Whats-wrong-with-always-quoting-vars of perlfaq4.

      (2) The line next unless -d $subdir; causes the foreach loop to skip to the next iteration (i.e., to ignore the current value of $subdir) unless the current $subdir is a directory (and not a file, a symbolic link, etc.). It uses the -d function which is documented in functions/-X.

      (3) The line chdir $dir . '/' . $subdir; contains two more concatenation operators, and is equivalent to:

      chdir "$dir/$subdir";

      Hope that helps,

      Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,