0

I am having issues getting my Perl script to recognize some subdirectories when traversing through my file system.

Please note that this is part of a homework assignment, and I am unable to use modules of any kind. I have attempted to troubleshoot this on my own for quite some time, and am now at a bit of a roadblock.

I am attempting to traverse a file structure, capture the names of all of the files, directories, and subdirectories into their respective arrays, and print them out in the illustrated format below:

Directory: ./  
Files: file1.text file2.pl file3.text  
Directories: subdir1 subdir2 subdir3  

Directory: subdir1  
Files: file3.text file4.pl  
Directories: subdir42  

...and so on.

I have attempted to use recursion as a solution to this, but my teacher indicated that recursion was not the appropriate way to handle this problem.

I have managed to print, in the appropriate format, the current working directory, and subdirectories within the current working directory.

For some reason, when I change the current code block to

if (-d $entry){
        next if $entry =~/^\./;
       push(@subdirs,"$entry");
       push(@dirs,"$currdir/$entry");
        }

      elsif(-f $entry) {
        push(@files,"$entry");
      }

It will omit some of the subdirectories.

Please see the entire script below.

#!/usr/bin/perl
use strict;
use warnings;


sub traverse {

my @dirs = ('.');
my @subdirs;
my @files;
  while(my $currdir = shift @dirs){

    opendir(my $dirhandle, $currdir) or die $!;

      while( my $entry = readdir $dirhandle){

      if (-d -r $entry){
        next if $entry =~/^\./;
       push(@subdirs,"$entry");
       push(@dirs,"$entry");
        }

      else {
        push(@files,"$entry");
      }

     }
      print "Directory: $currdir\n";
      print "Directories: ";
      print "@subdirs";
      print"\n";


      print "Files: ";
        foreach my $curfile (@files) {
            next if $curfile eq '.' or $curfile eq '..';

            if ($curfile =~ /(\S*\.delete)/){
                    unlink "$currdir/$curfile";
            }

            $curfile =~ s/txt$/text/;
            print "$curfile ";
        }

    print "\n";
    close $dirhandle;
    undef @files;
    undef @subdirs;

}
 return;
}
traverse();

And the current output:

Directory: .  
Directories: test dir_3 test2  
Files: recursion.text count_files.pl testing.text thelastone.pl testing.pl prog5_test.pl program51.pl program5.pl recursion.pl recurse.text prog52.pl  
dirs.pl

Directory: test  
Directories:  
Files: testfile1.text prog5_test.pl stilltesting program5.pl testfile2.text dirs.pl

Directory: dir_3  
Directories:  
Files:  

Directory: test2  
Directories:  
Files: file2.text moretesting file3.text  

stilltesting and moretesting should be recognized as directories.

Borodin
  • 126,100
  • 9
  • 70
  • 144
M.Wilson
  • 3
  • 1
  • 1
    You are checking `-r` - if it's not, it's a file? That seems strange logic - you should check whether it's a directory or a file - whether it's readable is another question which deserves separate treatment. – bytepusher Sep 03 '17 at 19:36
  • You should lay out your code more carefully: your indentation is all over the place. Also, you should remove the quotes from `"$entry"` as they are unnecessary, and in some cases can cause problems. – Borodin Sep 03 '17 at 21:57
  • 1
    Thanks @Borodin, you are absolutely right. I have modified the script per your suggestion. – M.Wilson Sep 04 '17 at 01:56
  • Thank you @bytepusher, I have removed the -r, as it is not relevant in the same loop as the -d. – M.Wilson Sep 04 '17 at 01:57

1 Answers1

1
if (-d $entry)

should be

if (-d "$currdir/$entry")

$entry is just a name in a directory. -d needs an actual path.

melpomene
  • 84,125
  • 8
  • 85
  • 148
  • Meaning `-d -r $entry` should be `-d $entry` should be `-d "$currdir/$entry"`. I was hoping he would see this after making a separate `-r $entry` (as a warning or exception). I was not entirely certain as to the homework policy, to be honest. – bytepusher Sep 03 '17 at 20:01
  • Thank you @melpomene, this was precisely what I was missing. The script now works as intended. – M.Wilson Sep 04 '17 at 01:57
  • @bytepusher, `-d -r "$currdir/$entry"` is perfectly fine. Since 5.10, it means `-d "$currdir/$entry" && -r "$currdir/$entry"` – ikegami Sep 04 '17 at 04:48
  • Interesting to know it did not mean that before 5.10, it is what I would have assumed. Thanks for clearing that up :) However, it still means a directory that is not readable is treated as a file by the OP's code due to the if/else construct – bytepusher Sep 04 '17 at 20:20