File Coverage

blib/lib/File/Iterator.pm
Criterion Covered Total %
statement 12 51 23.5
branch 0 22 0.0
condition 0 18 0.0
subroutine 4 9 44.4
pod 3 3 100.0
total 19 103 18.4


line stmt bran cond sub pod time code
1             package File::Iterator;
2              
3 1     1   551760 use 5.005;
  1         5  
  1         48  
4 1     1   6 use strict;
  1         2  
  1         126  
5 1     1   6 use Carp;
  1         14  
  1         89  
6 1     1   6 use vars qw($VERSION);
  1         2  
  1         907  
7              
8             $VERSION = '0.14';
9              
10             sub new {
11 0     0 1   my $proto = shift;
12 0   0       my $class = ref($proto) || $proto;
13 0           my $self = {
14             DIR => '.',
15             RECURSE => 1,
16             FILTER => undef,
17             RETURNDIRS => 0,
18             FOLLOWSYMLINKS => 0,
19             @_
20             };
21            
22 0           $self->{FILES} = [];
23 0           bless ($self, $class);
24            
25             # remove trailing slash unless user has supplied the root directory
26 0 0         if ( ! _isRootDir( $self->{DIR} ) ) {
27 0 0 0       if ( $^O eq "MSWin32" || $^O eq "os2") { # trailing slash can be either / or \
    0          
28 0           $self->{DIR} =~ s|[\\/]$||;
29             }
30             elsif ( $^O eq "NetWare" ) { # uses \ as directory separator
31 0           $self->{DIR} =~ s|\\$||;
32             }
33             else {
34 0           $self->{DIR} =~ s|/$||;
35             }
36             }
37            
38 0           $self->_probeDir( $self->{DIR} );
39 0           return $self;
40             }
41              
42             sub _isRootDir {
43 0     0     $_[0] =~ m{^(([a-z]:)?[\\/]|\\\\)$}i; # true if arg is /, \, X:\, X:/ or \\
44             }
45              
46             sub _probeDir {
47 0     0     my $self = shift;
48 0           my $dir = shift;
49 0 0 0       my $slash = _isRootDir($dir) ? "" : ( $^O eq "MSWin32" || $^O eq "NetWare" || $^O eq "os2" ) ? "\\" : "/";
    0          
50              
51 0 0         if (opendir DIR, $dir) {
52 0           my @files = grep { !/^\.{1,2}$/ } readdir DIR; # ignore . and ..
  0            
53 0           unshift @{$self->{FILES}}, map $dir.$slash.$_, sort { lc $a cmp lc $b } @files;
  0            
  0            
54 0           closedir DIR;
55             }
56             else {
57 0           carp "Can't open $dir: $!";
58             }
59             }
60              
61             sub next {
62 0     0 1   my $self = shift;
63 0 0         my $nextfile = shift @{$self->{FILES}} or return undef;
  0            
64 0 0         if (-d $nextfile) {
65             # if we are recursing and either the directory is not a symlink or we're following symlinks...
66 0 0 0       if ( $self->{RECURSE} && (!-l $nextfile || $self->{FOLLOWSYMLINKS} ) ) {
      0        
67 0           $self->_probeDir($nextfile);
68             }
69            
70 0 0         if (!$self->{RETURNDIRS}) {
71 0           return $self->next();
72             }
73             }
74              
75 0           my $filter = $self->{FILTER};
76 0 0 0       if ( $filter && !($filter->($nextfile)) ) {
77 0           return $self->next();
78             }
79             else {
80 0           return $nextfile;
81             }
82             }
83              
84             sub reset {
85 0     0 1   my $self = shift;
86 0           $self->{FILES} = [];
87 0           $self->_probeDir( $self->{DIR} );
88             }
89              
90             1;
91              
92             __END__