File Coverage

blib/lib/Filesys/Tree.pm
Criterion Covered Total %
statement 9 40 22.5
branch 0 30 0.0
condition n/a
subroutine 3 4 75.0
pod 1 1 100.0
total 13 75 17.3


line stmt bran cond sub pod time code
1             package Filesys::Tree;
2 1     1   29161 use File::Basename;
  1         3  
  1         134  
3              
4 1     1   8 use warnings;
  1         2  
  1         44  
5 1     1   6 use strict;
  1         8  
  1         852  
6              
7             =head1 NAME
8              
9             Filesys::Tree - Return contents of directories in a tree-like format
10              
11             =cut
12              
13             require Exporter;
14              
15             our @ISA = qw(Exporter);
16              
17             our %EXPORT_TAGS = (
18             'all' => [ qw(
19             tree
20             ) ],
21             );
22              
23             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
24              
25             our @EXPORT = qw(
26             );
27              
28             our $VERSION = '0.02';
29              
30             =head1 SYNOPSIS
31              
32             use Filesys::Tree qw/tree/;
33              
34             my $tree = tree('/path/to/directory');
35              
36             $tree now holds something like:
37              
38             {
39             a => {
40             type => 'd',
41             contents => {
42             1 => {
43             type => 'f',
44             },
45             },
46             }
47              
48             In this example, there is one directory named "a", which has a file
49             named "1".
50              
51             And you can also do:
52              
53             use Filesys::Tree qw/tree/;
54              
55             my $tree = tree( {'max-depth' => 2} , '/path/to/directory');
56              
57             See OPTIONS for a full list of options.
58              
59             =head1 FUNCTIONS
60              
61             =head2 tree
62              
63             This is currently the only function in the module. It returns a
64             tree-like representation of a directory (or a set of directories, if
65             you ask real hard).
66              
67             =cut
68              
69             sub tree {
70             # options
71 0     0 1   my %config = (
72             'max-depth' => -1,
73             full => 0,
74             );
75 0 0         if (ref($_[0]) eq 'HASH') {%config = (%config, %{+shift})}
  0            
  0            
76              
77             # building the tree
78 0 0         $config{'max-depth'} || return {};
79              
80 0           my $tree = {};
81              
82 0           for (@_) {
83 0           (my $basename = $_) =~ s/\/$//;
84 0 0         unless ($config{full}) {
85 0           $basename = basename($basename);
86             }
87              
88 0 0         if (-l) { # is a symbolic link
    0          
    0          
89 0 0         if ($config{'follow-links'}) { # we want to follow it
90 0 0         $tree->{$basename} = tree( { %config ,
91             'max-depth' => $config{'max-depth'} - 1 } ,
92 0           grep {$config{all} || /^[^.]/} readlink($_));
93             }
94             else {
95 0           next;
96             }
97             }
98              
99             elsif (-f) { # is a file
100 0 0         if (defined $config{'pattern'}) {
101 0 0         next unless $basename =~ /$config{'pattern'}/;
102             }
103 0 0         if (defined $config{'exclude-pattern'}) {
104 0 0         next if $basename =~ /$config{'exclude-pattern'}/;
105             }
106 0 0         next if $config{'directories-only'};
107 0           s/.*\/([^\/])$/$1/;
108 0           $tree->{$basename} = { type => 'f' };
109             }
110              
111             elsif (-d) { # is a directory
112 0           opendir(DIR,$_);
113 0           (my $dir = $_) =~ s{/$}{};
114 0           (my $sub = $dir);
115 0 0         $sub = basename($sub) unless $config{full};
116 0           $tree->{$sub} = { type => 'd' , contents =>
117             tree( { %config , 'max-depth' => $config{'max-depth'} - 1 } ,
118 0 0         map {"$dir/$_"}
119 0           grep {$config{all} || /^[^.]/}
120 0           grep {! /^\.\.?$/} readdir DIR ) };
121             }
122              
123             }
124              
125             # returning the tree
126 0           return $tree;
127             }
128              
129             =head1 OPTIONS
130              
131             =head2 all
132              
133             All files (by default, files beginning with a dot are not returned).
134             Default value is 0.
135              
136             Get a tree including all files:
137              
138             my $tree = tree( { all => 1 } , 'path/to/directory/' );
139              
140             =head2 max-depth
141              
142             Sets the max-depth for recursion. A negative number means there is no
143             max-depth. Default value is -1.
144              
145             Get a tree with a max depth of 2:
146              
147             my $tree = tree( { 'max-depth' => 2 , 'path/to/directory/' );
148              
149             =head2 directories-only
150              
151             Do not list files. Default value is 0.
152              
153             my $tree = tree( { 'directories-only' => 1 } , 'path/to/directory/' );
154              
155             =head2 full
156              
157             Full path for each entry. Default value is 0.
158              
159             Get a tree with full paths and prefixes:
160              
161             my $tree = tree( { 'full' => 1 } , 'path/to/directory' );
162              
163             =head2 follow-links
164              
165             Follows links. Default value is 0.
166              
167             Get a tree by following links:
168              
169             my $tree = tree( { 'follow-links' => 1 } , 'path/to/directory/' );
170              
171             =head2 pattern
172              
173             Only return filename matching pattern.
174              
175             Get a tree where only files in all lowercase characters are included:
176              
177             my $tree = tree( { 'pattern' => qr/^[a-z]+$/ } , 'path/to/directory/');
178              
179             =head2 exclude-pattern
180              
181             Exclude files matching the pattern.
182              
183             Get a tree excluding files with numeric names:
184              
185             my $tree = tree( { 'exclude-pattern' => qr/^\d+$/ } , 'path/to/directory/');
186              
187             =cut
188              
189             =head1 AUTHOR
190              
191             Jose Castro, C<< >>
192              
193             =head1 BUGS
194              
195             Please report any bugs or feature requests to
196             C, or through the web interface at
197             L. I will be notified, and then you'll automatically
198             be notified of progress on your bug as I make changes.
199              
200             =head1 SEE ALSO
201              
202             tree(1).
203              
204             =head1 COPYRIGHT & LICENSE
205              
206             Copyright 2005 Jose Castro, All Rights Reserved.
207              
208             This program is free software; you can redistribute it and/or modify it
209             under the same terms as Perl itself.
210              
211             =cut
212              
213             1; # End of Filesys::Tree