-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathList.pm
199 lines (133 loc) · 4.36 KB
/
List.pm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
package File::List;
use strict;
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
require Exporter;
@ISA = qw(Exporter);
# Items to export into callers namespace by default. Note: do not export
# names by default without a very good reason. Use EXPORT_OK instead.
# Do not simply export all your public functions/methods/constants.
@EXPORT = qw(
);
$VERSION = '0.3.1';
my $debug=0;
=head1 NAME
File::List - Perl extension for crawling directory trees and compiling lists of files
=head1 SYNOPSIS
use File::List;
my $search = new File::List("/usr/local");
$search->show_empty_dirs(); # toggle include empty directories in output
my @files = @{ $search->find("\.pl\$") }; # find all perl scripts in /usr/local
=head1 DESCRIPTION
This module crawls the directory tree starting at the provided base directory
and can return files (and/or directories if desired) matching a regular expression
=cut
=head1 INTERFACE
The following methods are available in this module.
=cut
=head2 new($base);
This creates a new File::List object and starts crawling the tree from this base
It takes a scalar base directory as an argument and returns an object reference
=cut
sub new {
my $class = shift;
my $base = shift;
my $self = {};
bless $self, $class;
# store my base for later
$self->{base} = $base;
$debug && print "spawned with base [$base]\n";
# read in contents of current directory
opendir (BASE, $base);
my @entries = grep !/^\.\.?\z/, readdir BASE;
chomp(@entries);
closedir(BASE);
for my $entry (@entries) {
# if entry is a directory, launch a new File::List to explore it
# and store a reference to the new object in the dirlist hash
if (-d "$base/$entry") {
$debug && print _trace(),"following directory $base/$entry\n";
my $newbase = new File::List("$base/$entry");
$self->{dirlist}{ $entry } = $newbase;
}
# if entry is a file, store it's name in the dirlist hash
elsif ( -f "$base/$entry"){
$debug && print _trace(),"Found file : $base/$entry\n";
$self->{dirlist}{ $entry } = 1;
}
}
return $self;
}
=head2 find($regexp);
This method accepts a scalar regular expression to search for.
It returns a reference to an array containing the full path to files
matching the expression (under this base).
=cut
sub find {
my $self = shift;
my $reg = shift;
my @result = ();
my $file;
for my $key (keys %{ $self->{dirlist} } ) {
# if we found a reference to a File::List, ask for it's find()
if ( ref ( $self->{dirlist}{ $key } ) ) {
$debug && print _trace(),"following directory".$self->{base}."/".$key."\n";
$self->{showdirs} && $self->{dirlist}{ $key }->show_empty_dirs();
$self->{onlydirs} && $self->{dirlist}{ $key }->show_only_dirs();
push @result, @{ $self->{dirlist}{ $key }->find($reg) };
}
# ah, found a file, push it into the results (if it matches the regexp)
else {
my $path = $self->{base}."/".$key;
$debug && print _trace(),"found file $path\n";
if ( ($path =~ eval{qr/$reg/}) && (! $self->{onlydirs}) ) {
push @result, ($path);
}
$file++;
}
}
if ( ( !$file && $self->{showdirs} || ( $self->{onlydirs} ) ) ){
$debug && print _trace(),"processing dir ".$self->{base}."\n";
push @result, ($self->{base}.'/') if ($self->{base} =~ eval {qr/$reg/} );
}
# we must be at the bottom level
return \@result;
}
=head2 debug($level);
This sets the debug level for find
=cut
sub debug {
my $self = shift;
$debug = shift;
return 1;
}
=head2 show_empty_dirs();
Toggle display of empty directories
=cut
sub show_empty_dirs {
my $self = shift;
$self->{showdirs} = $self->{showdirs}?undef:1;
return 1;
}
=head2 show_only_dirs();
Toggle display of just directories
=cut
sub show_only_dirs {
my $self = shift;
$self->{onlydirs} = $self->{onlydirs}?undef:1;
return 1;
}
#################
# Private methods, not to be used in the public API
#################
sub _trace {
my @timedat = localtime( time );
my $timestring = $timedat[ 2 ] . ':' . $timedat[ 1 ] . ':' . $timedat[ 0 ];
return @{[ ( caller( 1 )) [ 3 ] . "(): " . $timestring . "\t" ]};
}
1;
__END__
=head1 AUTHOR
Dennis Opacki, [email protected]
=head1 SEE ALSO
perl(1).
=cut