File Coverage

blib/lib/Dir/ListFilesRecursive.pm
Criterion Covered Total %
statement 100 126 79.3
branch 38 70 54.2
condition 5 14 35.7
subroutine 14 15 93.3
pod 3 3 100.0
total 160 228 70.1


line stmt bran cond sub pod time code
1             package Dir::ListFilesRecursive; ## Static functions to find files in directories.
2            
3            
4             our $VERSION='0.04';
5            
6            
7 2     2   3239 use strict;
  2         6  
  2         79  
8 2     2   12 use Carp;
  2         5  
  2         170  
9 2     2   22 use vars qw(@ISA @EXPORT %EXPORT_TAGS $VERSION);
  2         4  
  2         154  
10 2     2   23 use Exporter;
  2         3  
  2         89  
11 2     2   2255 use File::Spec::Functions;
  2         2086  
  2         3198  
12            
13            
14             @ISA = qw(Exporter);
15            
16             %EXPORT_TAGS = ( all => [qw(
17             list_files_flat
18             list_files_recursive
19             list_files_no_path
20             )] );
21            
22             Exporter::export_ok_tags('all');
23            
24            
25             # This class provides static functions which can be imported to the namespace of
26             # the current class. The functions lists the content of directories.
27             #
28             # With options you can filter the files for specific criteria, like no hidden files, etc.
29             #
30             # SYNOPSIS
31             # ========
32             #
33             # # imports all functions
34             # use Dir::ListFilesRecursive ':all';
35             #
36             # # imports only one function
37             # use Dir::ListFilesRecursive qw( list_files_recursive );
38             #
39             # use Data::Dumper;
40             # print Dumper( list_files_recursive('/etc') );
41             #
42             # use Data::Dumper;
43             # print Dumper( list_files_recursive('/etc', only_folders => 1) );
44             # # shows only subfolders of /etc
45             #
46             #
47             # Options
48             # =======
49             #
50             # For some functions, you can set options like the only_folders in the SYNOPSIS's example.
51             # You can use the following options:
52             # As options you can set these flags:
53             #
54             # only_folders => 1,
55             # only_files => 1,
56             # no_directories => 1,
57             # no_folders => 1,
58             # no_hidden_files => 1,
59             # extension => 'string',
60             # no_path => 1,
61             #
62             # You can also use various aliases:
63             #
64             # only_folders:
65             # only_folder, only_dir, only_dirs, only_directories, no_files
66             #
67             # no_directories:
68             # no_dir, no_dirs, no_folder, no_folders
69             #
70             # no_hidden_files:
71             # no_hidden
72             #
73             # extension:
74             # ext
75             #
76             # Not implemented so far: regular expression match, file age and other attributes.
77             #
78             #
79             #
80             # LICENSE
81             # =======
82             # You can redistribute it and/or modify it under the conditions of LGPL.
83             #
84             # AUTHOR
85             # ======
86             # Andreas Hernitscheck ahernit(AT)cpan.org
87            
88            
89            
90            
91            
92            
93             # List the files of a directory with full path.
94             #
95             # print list_files_flat('/etc');
96             # # may return files like:
97             # # /etc/hosts
98             # # /etc/passwd
99             #
100             # It does not return directory names. (that means 'flat'),
101             # only the files of given directory, no content of subfolders.
102             #
103             # You can set key value pairs to use further options.
104             # Please see chapter 'options'.
105             #
106             # It returns an array or arrayref, depending on context.
107             #
108             sub list_files_flat{ # array|arrayref ($path,%options)
109 1 50   1 1 24313 my $path = shift or croak "needs path";;
110 1         6 my %param = @_;
111 1         2 my @files;
112            
113             # extend params
114 1         7 my $param2 = _complete_params( \%param );
115 1         3 $param2->{'path'} = $path;
116 1         6 @files = grep { _does_filter_match_file( $_ , $param2 ) } _scan_dir( $path );
  24         43  
117            
118 1 50       6 if ( ! $param{'no_path'} ){
119 1         4 _add_path_to_array( $path, \@files );
120             }
121            
122            
123 1 50       16 return wantarray ? @files : \@files;
124             }
125            
126            
127            
128            
129            
130            
131            
132            
133            
134            
135             # List the files of a directory and subdirctories
136             # with full path.
137             #
138             # print list_files_recursive('/etc');
139             # # may return files like:
140             # # /etc/hosts
141             # # /etc/passwd
142             # # /etc/apache/httpd.conf
143             #
144             # You can set key value pairs to use further options.
145             # Please see chapter 'options'.
146             #
147             # It returns an array or arrayref, depending on context.
148             #
149             sub list_files_recursive { # array|arrayref ($path,%options)
150 2 50   2 1 308 my $path = shift or croak "needs path";
151 2         5 my %param = @_;
152 2         4 my @files;
153            
154             # extend params
155 2         7 my $param2 = _complete_params( \%param );
156             # $paths for _does_filter_match_file() not needed because list is with paths
157 2         8 @files = grep { _does_filter_match_file( $_ , $param2 ) } _list_files_recursive_nofilter( $path );
  286         487  
158            
159 2 50       22 if ( $param{'no_path'} ){
160 0         0 _sub_path_from_array( $path, \@files );
161             }
162            
163 2 50       75 return wantarray ? @files : \@files;
164             }
165            
166            
167             sub _list_files_recursive_nofilter { # array|arrayref ($path)
168 24 50   24   62 my $path = shift or croak "needs path";;
169 24         26 my @files;
170             my @filesm;
171            
172 24         47 @files = _scan_dir( $path );
173            
174             ## remove . and ..
175 24 100       58 @files = grep { $_ ne '.' and $_ ne '..' } @files;
  334         1351  
176            
177 24         66 _add_path_to_array( $path, \@files );
178            
179            
180             # step down a directory
181 24         44 foreach my $d ( @files ){
182 286 100       6681 if ( -d $d ){
183 22         55 push @filesm, _list_files_recursive_nofilter( $d ); # self call - recursive
184             }
185             }
186 24         90 push @files, @filesm;
187            
188 24         225 return @files;
189             }
190            
191            
192            
193            
194            
195            
196            
197            
198             # List the files of a directory without the path.
199             #
200             # print list_files_no_path('/etc');
201             # # may return files like:
202             # # hosts
203             # # passwd
204             #
205             # Furher subpaths will be returned like /etc/apache.
206             #
207             # You can set key value pairs to use further options.
208             # Please see chapter 'options'.
209             #
210             # It returns an array or arrayref, depending on context.
211             sub list_files_no_path{ # array|arrayref ($path,%options)
212 1 50   1 1 66 my $path = shift or croak "needs path";;
213 1         2 my %param = @_;
214 1         2 my @files;
215             my @nf;
216            
217 1         5 @files = list_files_recursive( $path, %param );
218            
219 1         9 foreach my $z (@files){
220 143         242 _sub_path_from_file( $path, \$z );
221             }
222            
223            
224            
225 1 50       46 return wantarray ? @files : \@files;
226             }
227            
228            
229            
230             # scanns a dir simple and flat
231             sub _scan_dir {
232 25 50   25   66 my $path = shift or croak "needs path";
233 25         41 my @files;
234            
235 25         820 opendir( FDIR, $path );
236 25         719 @files = readdir FDIR; ;
237 25         271 closedir( FDIR );
238            
239             # remove . and ..
240 25 50       81 if ($files[0] =~ m/^\.\.?$/ ){ shift @files };
  0         0  
241 25 50       59 if ($files[0] =~ m/^\.\.?$/ ){ shift @files };
  0         0  
242            
243            
244 25 50       180 return wantarray ? @files : \@files;
245             }
246            
247            
248            
249            
250             sub _complete_params {
251 3     3   5 my $p1 = shift;
252 3         9 my $p2 = {};
253            
254             # copy params
255 3         4 %{ $p2 } = %{ $p1 };
  3         7  
  3         7  
256            
257 3 50       11 if ($p1->{only_folder}) {$p2->{no_files}=1};
  0         0  
258 3 50       13 if ($p1->{only_folders}) {$p2->{no_files}=1};
  0         0  
259 3 50       11 if ($p1->{only_dir}) {$p2->{no_files}=1};
  0         0  
260 3 50       10 if ($p1->{only_dirs}) {$p2->{no_files}=1};
  0         0  
261 3 50       7 if ($p1->{only_directories}) {$p2->{no_files}=1};
  0         0  
262            
263 3 50       11 if ($p1->{only_files}) {$p2->{no_dir}=1};
  0         0  
264            
265 3         7 return $p2;
266             }
267            
268            
269            
270             sub _does_filter_match_file{
271 310     310   386 my $f = shift;
272 310         327 my $param = shift;
273 310         298 my @nf;
274 310         411 my $path = $param->{path};
275 310         318 my $ok = 1;
276            
277 310   100     699 $param->{no_files} //= '';
278            
279 310         263 my $chkf_d;
280            
281 310 100       436 if ( $path ){
282 24         584 $chkf_d = -d catfile($path,$f);
283             }else{
284 286         6559 $chkf_d = -d $f;
285             }
286            
287            
288 310 50 33     1029 if (($param->{no_files} ne '') && ( ! $chkf_d )){
289             #$ok = 0;
290 0         0 return 0;
291             };
292            
293 310 100       554 if ( $chkf_d ){
294            
295 35 50       75 if ($param->{no_dir}) { return 0 };
  0         0  
296 35 50       67 if ($param->{no_dirs}) { return 0 };
  0         0  
297 35 50       72 if ($param->{no_directories}){ return 0 };
  0         0  
298 35 50       72 if ($param->{no_folder}) { return 0 };
  0         0  
299 35 50       70 if ($param->{no_folders}) { return 0 };
  0         0  
300            
301 35 50       74 if ( !$ok ){
302 0         0 return 0;
303             }
304            
305            
306             }
307            
308            
309            
310 310 50 33     1510 if ( ( ($param->{no_hidden}) || ($param->{no_hidden_files}) )
      33        
311             && ( index($f,'.') == 0 )
312             ){
313 0         0 return 0;
314             };
315            
316            
317 310 50       669 if ( exists $param->{ext} ){
318 0   0     0 my $ext = lc($param->{ext}) || lc($param->{extension});
319 0 0       0 if ( $f=~ m/\.$ext$/i ){ $ok=1 }else{ $ok=0 };
  0         0  
  0         0  
320             }
321            
322 310         739 return $ok;
323             }
324            
325            
326            
327            
328            
329            
330            
331            
332            
333             # helper method to add the path to the found files.
334             sub _add_path_to_array{
335 25     25   59 my $path=shift;
336 25         30 my $dir_ref=shift;
337            
338 25         43 foreach my $z (@$dir_ref){
339 310         5403 $z=catfile($path,$z);
340             }
341             }
342            
343            
344             # helper method to remove path from found files
345             sub _sub_path_from_array{
346 0     0   0 my $path=shift;
347 0         0 my $dir_ref=shift;
348            
349 0         0 my $slash = catdir('','');
350            
351 0         0 foreach my $z (@$dir_ref){
352 0         0 _sub_path_from_file( $path, \$z );
353             }
354             }
355            
356            
357             sub _sub_path_from_file{
358 143 50   143   292 my $path=shift or croak "needs path";
359 143 50       285 my $file_ref=shift or croak "needs fileref";
360            
361 143         424 my $slash = catdir('','');
362            
363 143         983 $$file_ref =~ s/^\Q$path\E[\Q$slash\E]?//;
364            
365             }
366            
367            
368            
369            
370            
371             1;
372             #################### pod generated by Pod::Autopod - keep this line to make pod updates possible ####################
373            
374             =head1 NAME
375            
376             Dir::ListFilesRecursive - Static functions to find files in directories.
377            
378            
379             =head1 SYNOPSIS
380            
381            
382             # imports all functions
383             use Dir::ListFilesRecursive ':all';
384            
385             # imports only one function
386             use Dir::ListFilesRecursive qw( list_files_recursive );
387            
388             use Data::Dumper;
389             print Dumper( list_files_recursive('/etc') );
390            
391             use Data::Dumper;
392             print Dumper( list_files_recursive('/etc', only_folders => 1) );
393             # shows only subfolders of /etc
394            
395            
396            
397            
398             =head1 DESCRIPTION
399            
400             This class provides static functions which can be imported to the namespace of
401             the current class. The functions lists the content of directories.
402            
403             With options you can filter the files for specific criteria, like no hidden files, etc.
404            
405            
406            
407             =head1 REQUIRES
408            
409             L
410            
411            
412             =head1 METHODS
413            
414             =head2 list_files_flat
415            
416             my @array | \@arrayref = list_files_flat($path, %options);
417            
418             List the files of a directory with full path.
419            
420             print list_files_flat('/etc');
421             # may return files like:
422             # /etc/hosts
423             # /etc/passwd
424            
425             It does not return directory names. (that means 'flat'),
426             only the files of given directory.
427            
428             You can set key value pairs to use further options.
429             Please see chapter 'options'.
430            
431             It returns an array or arrayref, depending on context.
432            
433            
434            
435             =head2 list_files_no_path
436            
437             my @array | \@arrayref = list_files_no_path($path, %options);
438            
439             List the files of a directory without the path.
440            
441             print list_files_no_path('/etc');
442             # may return files like:
443             # hosts
444             # passwd
445            
446             It does not return directory names.
447            
448             You can set key value pairs to use further options.
449             Please see chapter 'options'.
450            
451             It returns an array or arrayref, depending on context.
452            
453            
454             =head2 list_files_recursive
455            
456             my @array | \@arrayref = list_files_recursive($path, %options);
457            
458             List the files of a directory and subdirctories
459             with full path.
460            
461             print list_files_recursive('/etc');
462             # may return files like:
463             # /etc/hosts
464             # /etc/passwd
465             # /etc/apache/httpd.conf
466            
467             You can set key value pairs to use further options.
468             Please see chapter 'options'.
469            
470             It returns an array or arrayref, depending on context.
471            
472            
473            
474            
475             =head1 Options
476            
477            
478             For some functions, you can set options like the only_folders in the SYNOPSIS's example.
479             You can use the following options:
480             As options you can set these flags:
481            
482             only_folders => 1,
483             only_files => 1,
484             no_directories => 1,
485             no_folders => 1,
486             no_hidden_files => 1,
487             extension => 'string',
488             no_path => 1,
489            
490             You can also use various aliases:
491            
492             only_folders:
493             only_folder, only_dir, only_dirs, only_directories, no_files
494            
495             no_directories:
496             no_dir, no_dirs, no_folder, no_folders
497            
498             no_hidden_files:
499             no_hidden
500            
501             extension:
502             ext
503            
504             Not implemented so far: regular expression match, file age and other attributes.
505            
506            
507            
508            
509            
510             =head1 AUTHOR
511            
512             Andreas Hernitscheck ahernit(AT)cpan.org
513            
514            
515             =head1 LICENSE
516            
517             You can redistribute it and/or modify it under the conditions of LGPL.
518            
519            
520            
521             =cut