How can I recursively read out directories in Perl?

前端 未结 6 2404
一生所求
一生所求 2021-02-14 06:08

I want to read out a directory recursively to print the data-structure in an HTML-Page with Template::Toolkit. But I\'m hanging in how to save the Paths and Files in a form that

相关标签:
6条回答
  • 2021-02-14 06:21

    The answer by mdom explains how your initial attempt went astray. I would also suggest that you consider friendlier alternatives to File::Find. CPAN has several options. Here's one.

    use strict;
    use warnings;
    use File::Find::Rule;
    my @paths = File::Find::Rule->in(@ARGV);
    

    Also see here:

    • SO answer providing CPAN alternatives to File::Find.

    • SO question on directory iterators.

    And here is a rewrite of your recursive solution. Things to note: use strict; use warnings; and the use of a scoping block to create a static variable for the subroutine.

    use strict;
    use warnings;
    
    print $_, "\n" for dir_listing(@ARGV);
    
    {
        my @paths;
        sub dir_listing {
            my ($root) = @_;
            $root .= '/' unless $root =~ /\/$/;
            for my $f (glob "$root*"){
                push @paths, $f;
                dir_listing($f) if -d $f;
            }
            return @paths;
        }
    }
    
    0 讨论(0)
  • 2021-02-14 06:26

    You should always use strict and warnings to help you debug your code. Perl would have warned you for example that @files is not declared. But the real problem with your function is that you declare a lexical variable @paths on every recursive call to list_dirs and don't push the return value back after the recursion step.

    push @paths, list_dir($eachFile)
    

    If you don't want to install additional modules, the following solution should probably help you:

    use strict;
    use warnings;
    use File::Find qw(find);
    
    sub list_dirs {
            my @dirs = @_;
            my @files;
            find({ wanted => sub { push @files, $_ } , no_chdir => 1 }, @dirs);
            return @files;
    }
    
    0 讨论(0)
  • 2021-02-14 06:31

    you can use this method as recursive file search that separate specific file types,

    my @files;
    push @files, list_dir($outputDir);
    
    sub list_dir {
            my @dirs = @_;
            my @files;
            find({ wanted => sub { push @files, glob "\"$_/*.txt\"" } , no_chdir => 1 }, @dirs);
            return @files;
    }
    
    0 讨论(0)
  • 2021-02-14 06:39

    I use this script to remove hidden files (created by Mac OS X) from my USB Pendrive, where I usually use it to listen music in the car, and any file ending with ".mp3", even when it starts with "._", will be listed in the car audio list.

    #!/bin/perl
    
    use strict;
    use warnings;
    
    use File::Find qw(find);
    
    sub list_dirs {
            my @dirs = @_;
            my @files;
            find({ wanted => sub { push @files, $_ } , no_chdir => 1 }, @dirs);
            return @files;
    }
    
    if ( ! @ARGV || !$ARGV[0] ) {
      print "** Invalid dir!\n";
      exit ;
    }
    
    
    if ( $ARGV[0] !~ /\/Volumes\/\w/s ) {
      print "** Dir should be at /Volume/... > $ARGV[0]\n";
      exit ;
    }
    
    my @paths = list_dirs($ARGV[0]) ;
    
    foreach my $file (@paths) {
      my ($filename) = ( $file =~ /([^\\\/]+)$/s ) ;
    
      if ($filename =~ /^\._/s ) {
        unlink $file ;
        print "rm> $file\n" ;
      }
    }
    
    0 讨论(0)
  • 2021-02-14 06:41

    I think you have problem in the following line in your code

    for my $eachFile (glob($path.'*'))
    

    You change the $path variable into $rootpath.

    It will store the path correctly.

    0 讨论(0)
  • 2021-02-14 06:45

    This should do the trick

     use strict;
     use warnings;
     use File::Find qw(finddepth);
     my @files;
     finddepth(sub {
          return if($_ eq '.' || $_ eq '..');
          push @files, $File::Find::name;
     }, '/my/dir/to/search');
    
    0 讨论(0)
提交回复
热议问题