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

Hi Monks,

I have a directory structure like shown below

-------------------------------------------------
Directory: /proj/newdata/ Files: alpha.seq, beta.pm, gamma.txt Sub Directories: dog, cat Sub-Directory:dog Files: batman0.seq, batman1.txt Sub Directories: D1, D2 Sub-Directory: D1 Files: joker0.seq, joker1.pm Sub Directories: C0 Sub-Directory: C0 Files: file0.seq, file1.pm, file.txt Sub-Directory:cat Files: man0.seq, man1.txt Sub Directories: D3, D4 Sub-Directory: D3 Files: jok0.seq, jok1.pm Sub Directories: C1 Sub-Directory: C1 Files: f0.seq, f1.pm, f.txt
---------------------------------------------------

Now I want a perl script which can take the input directory name '/proj/newdata' and find all the files that end only with .seq and .pm and print them according to their directory structure like this:

RESULT: -------------------------------------------------

Group: /proj/newdata { File: alpha.seq (/proj/newdata/alpha.seq) File: beta.pm (/proj/newdata/beta.pm) Group: dog { File: batman0.seq (/proj/newdata/dog/batman0.seq) Group: D1 { File: joker0.seq (/proj/newdata/dog/D1/joker0.seq) File: joker1.pm (/proj/newdata/dog/D1/joker1.pm) Group: C0 { File: file0.seq (/proj/newdata/dog/D1/C0/file0.seq) File: file11.pm (/proj/newdata/dog/D1/C0/file1.pm) } #Group C0 } # Group D1 } # Group Dog Group: cat { File: man0.seq (/proj/newdata/cat/man0.seq) Group: D3 { File: jok0.seq (/proj/newdata/cat/D3/jok0.seq) File: jok1.pm (/proj/newdata/cat/D3/jok1.pm) Group: C1 { File: f0.seq (/proj/newdata/dog/D3/C1/file0.seq) File: f1.pm (/proj/newdata/dog/D3/C1/file1.pm) } #Group C1 } # Group D3 } # Group Cat } # Group /proj/newdata

-------------------------------------------------------

The words after "#" are comments and are not required.

Any help would be appreciated. I used File::Find and some other ways but could not crack the correct directory structuring printing and it's been some time I am working on this.

Thankyou

Replies are listed 'Best First'.
Re: Traverse through directory structure and print in required format
by GrandFather (Saint) on Mar 14, 2011 at 23:03 UTC

    So show us the code you have tried and tell us where the problem is. File::Find is likely to be an appropriate part of the puzzle so show us the code you tried using it.

    True laziness is hard work
Re: Traverse through directory structure and print in required format
by Anonymous Monk on Mar 14, 2011 at 22:58 UTC
    printing and it's been some time I am working on this.

    Then you should show your effort

Re: Traverse through directory structure and print in required format
by ikegami (Patriarch) on Mar 14, 2011 at 23:05 UTC
    use File::Basename qw( basename ); sub visit { my ($dir, $level) = @_; $level ||= 0; my $group_indent = ' ' x (2*$level); ++$level; my $child_indent = ' ' x (2*$level); printf($group_indent."Group: %s {\n", $level ? basename($dir) : $di +r); my @file_names = do { opendir(my $dh, $dir); grep !/^\.\.?\z/, readdir($dh) }; for my $fn (@file_names) { my $qfn = "$dir/$fn"; if (-d $qfn) { visit($qfn, $level); } else { print($child_indent."File: $fn ($qfn)\n"); } } print($group_indent."}\n"); } visit('/proj/newdata');

    Possible improvements:

    • Error checking for opendir.
    • Error checking for -d (although it's not likely to return an error if you were just able to read the directory).
    • Make "$dir/$fn" portable. (It will fail if you give "C:" as the initial directory on a Windows machine if the current directory for drive C: isn't the root directory.)

    Update: Was missing top level Group. Fixed.

      This includes all the possible improvements I mentioned:
      use Path::Class qw( dir ); sub visit { my ($dir, $level) = @_; $level ||= 0; my $group_indent = ' ' x (2*$level); ++$level; my $child_indent = ' ' x (2*$level); printf($group_indent."Group: %s {\n", $level ? $dir->basename : $di +r); for my $file (dir($dir)->children()) { if ($file->is_dir) { visit($file, $level); } else { printf($child_indent."File: %s (%s)\n", $file->basename, $fil +e); } } print($group_indent."}\n"); } visit('/proj/newdata');

      Update: Was missing top level Group. Fixed.