File Coverage

blib/lib/File/Wildcard.pm
Criterion Covered Total %
statement 226 227 99.5
branch 85 92 92.3
condition 44 51 86.2
subroutine 29 29 100.0
pod 8 8 100.0
total 392 407 96.3


line stmt bran cond sub pod time code
1              
2             package File::Wildcard;
3 6     6   190992 use strict;
  6         20  
  6         813  
4              
5             our $VERSION = '0.11';
6              
7             =head1 NAME
8              
9             File::Wildcard - Enhanced glob processing
10              
11             =head1 SYNOPSIS
12              
13             use File::Wildcard;
14             my $foo = File::Wildcard->new(path => "/home/me///core");
15             while (my $file = $foo->next) {
16             unlink $file;
17             }
18            
19             =head1 DESCRIPTION
20              
21             When looking at how various operating systems do filename wildcard expansion
22             (globbing), VMS has a nice syntax which allows expansion and searching of
23             whole directory trees. It would be nice if other operating systems had
24             something like this built in. The best Unix can manage is through the
25             utility program C.
26              
27             This module provides this facility to Perl. Whereas native VMS syntax uses
28             the ellipsis "...", this will not fit in with POSIX filenames, as ... is a
29             valid (though somewhat strange) filename. Instead, the construct "///" is
30             used as this cannot syntactically be part of a filename, as you do not get
31             three concurrent filename separators with nothing between (three slashes
32             are used to avoid confusion with //node/path/name syntax).
33              
34             You don't have to use this syntax, as you can do the splitting yourself and
35             pass in an arrayref as your path.
36              
37             The module also forms a B for the whole of the wildcard
38             string, and binds a series of back references ($1, $2
39             etc.) which are available to construct new filenames.
40              
41             =head2 new
42              
43             Cnew( $wildcard, [,option => value,...]);>
44              
45             my $foo = File::Wildcard->new( path => "/home/me///core");
46             my $srcfnd = File::Wildcard->new( path => "src///*.cpp",
47             match => qr(^src/(.*?)\.cpp$),
48             derive => ['src/$1.o','src/$1.hpp']);
49              
50             This is the constructor for File::Wildcard objects. At a simple level,
51             pass a single wildcard string as a path.
52              
53             For more complicated operations, you can supply your own match regexp, or
54             use the derive option to specify regular expression captures to form
55             the basis of other filenames that are constructed for you.
56              
57             The $srcfnd example gives you object files and header files corresponding
58             to C++ source files.
59              
60             Here are the options that are available:
61              
62             =over 4
63              
64             =item C
65              
66             This is the input parameter that specifies the range
67             of files that will be looked at. This is a glob spec which can also contain
68             the ellipsis '///' (it could contain more than one ellipsis, but the benefit
69             of this is questionable, and multiple ellipsi would cause a performance hit).
70              
71             Note that the path can be relative or absolute. B will do the right
72             thing, working out that a path starting with '/' is absolute. In order
73             to recurse from the current directory downwards, specify './//foo'.
74              
75             As an alternative, you can supply an arrayref with the path constituents
76             already split. If you do this, you need to tell B if the path is absolute.
77             Include an empty string for an ellipsis. For example:
78              
79             'foo///bar/*.c' is equivalent to ['foo','','bar','*.c']
80              
81             You can also construct a File::Wildcard without a path. A call to
82             B will return undef, but paths can be added using the append and prepend
83             methods.
84              
85             =item C
86              
87             This is ignored unless you are using a pre split path. If you
88             are passing a string as the path, B will work out whether the path is
89             absolute or relative. Pass a true value for absolute paths.
90              
91             If your original filespec started with '/' before you split it, specify
92             absolute => 1. B is not required for Windows if the path contains
93             a drive specification, e.g. C:/foo/bar.
94              
95             =item C
96              
97             By default, the module will use L to determine whether the
98             file system of your wildcard is defined. This is an optional module (see
99             L), and File::Wildcard will guess at case sensitivity
100             based on your operating system. This will not always be correct, as the
101             file system might be VFAT mounted on Linux or ODS-5 on VMS.
102              
103             Specifying the option C explicitly forces this behaviour
104             on the wildcard.
105              
106             Note that File::Wildcard will use the file system of the current working
107             directory if the path is not absolute. If the path is absolute, you should
108             specify the case_sensitivity option explicitly.
109              
110             =item C
111              
112             You can provide a regexp to apply to any generated paths, which will cause
113             any matching paths not to be processed. If the root of a directory tree
114             matches, no processing is done on the entire tree.
115              
116             This option can be useful for excluding version control repositories, e.g.
117              
118             exclude => qr/.svn/
119              
120             =item C
121              
122             Optional. If you do not specify a regexp, you get all the files
123             that match the glob; in addition, B will set up a regexp for you, to
124             provide a capture for each wildcard used in the path.
125              
126             If you do provide a match parameter, this will be used instead, and will
127             filter the results.
128              
129             =item C
130              
131             Supply an arrayref with a list of derived filenames, which
132             will be constructed for each matching file. This causes B to return
133             an arrayref instead of a scalar.
134              
135             =item C
136              
137             If given a true value indicates that symbolic links are to be followed. Otherwise,
138             the symbolic link target itself is presented, but the ellipsis will not traverse
139             the link.
140              
141             This module detects a looping symlink that points to a directory higher up, and
142             will only present the tree once.
143              
144             =item C
145              
146             This can take one of the following values: normal, breadth-first, inside-out.
147             The default option is normal. This controls how File::Wildcard handles
148             the ellipsis. The default is a normal depth first search, presenting the
149             name of each containing directory before the contents.
150              
151             The inside-out order presents the contents of directories first before
152             the directory, which is useful when you want to remove files and directories
153             (all O/S require directories to be empty before rmdir will work). See
154             t/03_absolute.t as this uses inside-out order to tidy up after the test.
155              
156             Breadth-first is rarely needed (but I do have an application for it). Here,
157             the whole directory contents is presented before traversing any subdirectories.
158              
159             Consider the following tree:
160             a/
161             a/bar/
162             a/bar/drink
163             a/foo/
164             a/foo/lish
165              
166             breadth-first will give the following order: qw(a/ a/bar/ a/foo/ a/bar/drink
167             a/foo/lish). normal gives the order in which the files are listed.
168             inside-out gives the following: qw(a/bar/drink a/bar/ a/foo/lish a/foo/ a/).
169              
170             =item C
171              
172             By default, globbing returns the list of files in the order in which they
173             are returned by the dirhandle (internally). If you specify sort => 1, the
174             files are sorted into ASCII sequence (case insensitively if we are operating
175             that way). If you specify a CODEREF, this will
176             be used as a comparison routine. Note that this takes its operands in @_,
177             not in $a and $b.
178              
179             =item C and C
180              
181             You can enable a trace of the internal states of File::Wildcard by setting
182             debug to a true value. Set debug_output to an open filehandle to get the
183             trace in a file. If you are submitting bug reports for File::Wildcard, attaching
184             debug trace files would be very useful.
185              
186             debug_output defaults to STDERR.
187              
188             =back
189              
190             =head2 match
191              
192             my $foo_re = $foo->match;
193             $foo->match('bar/core');
194              
195             This is a get and set method that gives access to the match regexp that
196             the File::Wildcard object is using. It is possible to change the regex
197             on the fly in the middle of a search (though I don't know why anyone would
198             want to do this).
199              
200             =head2 append
201              
202             $foo->append(path => '/home/me///*.tmp');
203              
204             appends a path to an object's todo list. This will be globbed
205             after the object has finished processing the existing wildcards.
206              
207             =head2 prepend
208              
209             $srcfnd->prepend(path => $include_file);
210              
211             This is similar to append, but prepends the path to the todo list. In other
212             words, the current wildcard operation is interrupted to serve the new path,
213             then the previous wildcard operation is resumed when this is exhausted.
214              
215             =head2 next
216              
217             while (my $core = $foo->next) {
218             unlink $core;
219             }
220             my ($src,$obj,$hdr) = @{$srcfnd->next};
221              
222             The C method is an iterator, which returns successive files. Returns
223             matching files if there was no derive option passed to new. If there was
224             a derive option, returns an arrayref containing the matching filespec and
225             all derived filespecs. The derived filespecs do not have to exist.
226              
227             Note that C maintains an internal cursor, which retains context and
228             state information. Beware if the contents of directories are changing while
229             you are iterating with next; you may get unpredictable results. If you are
230             intending to change the contents of the directories you are scanning (with unlink
231             or rename), you are better off deferring this operation until you have processed
232             the whole tree. For the pending delete or rename operations, you could always
233             use another File::Wildcard object - see the spike example below:
234              
235             =head2 all
236              
237             my @cores = $foo->all;
238              
239             C returns an array of matching files, in the simple case. Returns an
240             array of arrays if you are constructing new filenames, like the $srcfnd
241             example.
242              
243             Beware of the performance and memory implications of using C. The
244             method will not return until it has read the entire directory tree. Use of
245             the C method is not recommended for traversing large directory trees
246             and whole file systems. Consider coding the traversal using the iterator
247             C instead.
248              
249             =head2 reset
250              
251             C causes the wildcard context to be set to re-read the first filename
252             again. Note that this will cause directory contents to be re-read.
253              
254             Note also that this will cause the path to revert to the original path
255             specified to B. Any additional paths appended or prepended will be
256             forgotten.
257              
258             =head2 close
259              
260             Release all directory handles associated with the File::Wildcard object.
261             An object that has been closed will be garbage collected once it goes out
262             of scope. Wildcards that have been exhausted are automatically closed,
263             (i.e. C was used, or c returned undef).
264              
265             Subsequent calls to C will return undef. It is possible to call
266             C after C on the same File::Wildcard object, which will cause
267             it to be reopened.
268              
269             =head1 EXAMPLES
270              
271             =over 4
272              
273             =item *
274             B
275              
276             my $todo = File::Wildcard->new;
277              
278             ...
279              
280             $todo->append(path => $file);
281              
282             ...
283              
284             while (my $file = $todo->next) {
285             ...
286             }
287              
288             You can use an empty wildcard to store a list of filenames for later
289             processing. The order in which they will be seen depends on whether append
290             or prepend is used.
291              
292             =item *
293             B
294              
295             my $wc_args = File::Wildcard->new;
296              
297             $wc_args->append(path => $_) for @ARGV;
298              
299             while ($wc_args->next) {
300             ...
301             }
302              
303             On Unix, file wildcards on the command line are globbed by the shell before
304             perl sees them, unless the wildcards are escaped or quoted. This is not true
305             of other operating systems. MS-DOS does no globbing at all for example.
306              
307             File::Wildcard gives you the bonus of elliptic globbing with '///'.
308              
309             =back
310              
311             =head1 CAVEAT
312              
313             This module takes POSIX filenames, which use forward slash '/' as a
314             path separator. All operating systems that run Perl can manage this type
315             of path. The module is not designed to work with B file specs.
316             If you want to write code that is portable, convert native filespecs to
317             the POSIX form. There is of course no difference on Unix platforms.
318            
319             =head1 BUGS
320              
321             Please report bugs to http://rt.cpan.org
322              
323             =head1 AUTHOR
324              
325             Ivor Williams
326             ivorw-file-wildcard010 at xemaps.com
327              
328             =head1 COPYRIGHT
329              
330             This program is free software; you can redistribute
331             it and/or modify it under the same terms as Perl itself.
332              
333             The full text of the license can be found in the
334             LICENSE file included with this module.
335              
336              
337             =head1 SEE ALSO
338              
339             glob(3), L, L.
340              
341             =cut
342              
343 6     6   12160 use Params::Validate::Dummy qw();
  6         6580  
  6         154  
344 6     6   5725 use Module::Optional qw(Params::Validate :all);
  6         4773  
  6         34  
345              
346             package Filesys::Type::Dummy;
347 6     6   4672 use strict;
  6         11  
  6         837  
348              
349             sub case {
350 10 50   10   896 return 'insensitive' if $^O =~ /win|dos/i;
351 10 50       40 return 'lower' if $^O =~ /vms/i;
352 10         50 return 'sensitive';
353             }
354              
355             package File::Wildcard;
356 6     6   71 use Module::Optional qw(Filesys::Type);
  6         18  
  6         27  
357 6     6   5195 use File::Spec;
  6         10  
  6         118  
358 6     6   28 use Carp;
  6         9  
  6         19764  
359              
360             sub new {
361 28     28 1 12055 my $pkg = shift;
362              
363 28         663 my %par = validate(
364             @_,
365             { derive => 0,
366             path => { type => SCALAR | ARRAYREF, optional => 1 },
367             follow => 0,
368             absolute => 0,
369             match => { type => SCALARREF, optional => 1 },
370             exclude => { type => SCALARREF, optional => 1 },
371             sort => { type => SCALAR | CODEREF | UNDEF, optional => 1 },
372             ellipsis_order => {
373             type => SCALAR,
374             regex => qr/(normal|breadth-first|inside-out)/,
375             optional => 1,
376             },
377             case_insensitive => { type => SCALAR, optional => 1 },
378             debug => { type => SCALAR, optional => 1 },
379             debug_output => 0,
380             }
381             );
382              
383 28   100     554 $par{ellipsis_order} ||= 'normal';
384 28         51 my $path = $par{path}; # $par{path} is about to be chopped up
385 28         135 ( $par{path}, $par{absolute} )
386             = $pkg->_split_path( @par{qw/path absolute follow/} );
387 28 100 66     196 if ( exists( $par{path} ) && !defined $par{case_insensitive} ) {
388 9 50       143 my $fspath = $par{absolute} ? $path : File::Spec->curdir;
389 9   33     20 my $fscase = eval { Filesys::Type::case($fspath) }
390             || Filesys::Type::Dummy::case;
391 9         32 $par{case_insensitive} = $fscase eq 'sensitive';
392             }
393              
394 28 100 50     127 $par{debug_output} ||= \*STDERR if $par{debug};
395              
396 28 50       200 unless ( exists $par{match} ) {
397 28 100       87 my $match_re = $par{absolute} ? '^/' : '^';
398 28         43 for ( @{ $par{path} } ) {
  28         78  
399 76         132 my $comp = quotemeta $_;
400 76         125 $comp =~ s!((?:\\\?)+)!'(.{'.(length($1)/2).'})'!eg;
  3         51  
401 76         108 $comp =~ s!\\\*!([^/]*)!g;
402 76   100     263 $match_re .= ( $comp || '(.*?)' ) . '/';
403             }
404 28         122 $match_re =~ s!/$!\$!;
405 28 100       668 $par{match} = $par{case_insensitive} ? qr/$match_re/i : qr/$match_re/;
406             }
407              
408 28         811 bless \%par, $pkg;
409             }
410              
411             sub _debug {
412 12292     12292   16906 my ( $self, $mess ) = @_;
413              
414 12292 100       30656 return unless $self->{debug};
415 4796         6463 my $dbug = $self->{debug_output};
416              
417 4796         13056 print $dbug $mess;
418             }
419              
420             sub next {
421 104     104 1 6165 my $self = shift;
422              
423 104 100       340 $self->_set_state( state => 'initial' ) unless exists $self->{state};
424              
425 104         259 while ( !exists $self->{retval} ) {
426 5215         19009 $self->_debug( "In state " . $self->{state} . "\n" );
427 5215         14994 my $method = "_state_" . $self->{state};
428 5215         12021 $self->$method;
429             }
430 104   100     723 $self->_debug( "Returned " . ( $self->{retval} || 'undef' ) . "\n" );
431 104         173 my $rv = $self->{retval};
432 104         214 delete $self->{retval};
433              
434 104         456 $rv;
435             }
436              
437             sub all {
438 21     21 1 15434 my $self = shift;
439              
440 21         40 my @out;
441              
442 21         59 while ( my $match = $self->next ) {
443 58         202 push @out, $match;
444             }
445              
446 21         130 @out;
447              
448             }
449              
450             sub close {
451 2     2 1 4 my $self = shift;
452              
453 2         6 delete $self->{stack};
454 2         5 delete $self->{dir};
455 2         4 delete $self->{seen_symlink};
456 2         6 $self->_set_state( state => 'finished' );
457             }
458              
459             sub reset {
460 2     2 1 1725 my $self = shift;
461              
462 2         8 $self->close;
463 2         7 $self->_set_state( state => 'initial' );
464             }
465              
466             sub _derived {
467 70     70   103 my $self = shift;
468              
469 70 100       316 return $self->{resulting_path} unless exists $self->{derive};
470              
471 5         12 my @out = ( $self->{resulting_path} );
472 5         7 my $re = $self->{match};
473 5         28 $self->{resulting_path} =~ /$re/;
474 5         6 for ( @{ $self->{derive} } ) {
  5         13  
475 5         437 push @out, eval(qq("$_"));
476             }
477              
478 5         18 \@out;
479             }
480              
481             sub match {
482 4     4 1 53 my $self = shift;
483              
484 4         29 my ($new_re) = validate_pos( @_, { type => SCALARREF, optional => 1 } );
485              
486 4 100       45 $new_re ? ( $self->{match} = $new_re ) : $self->{match};
487             }
488              
489             sub append {
490 5     5 1 8373 my $self = shift;
491              
492 5         37 my %par = validate(
493             @_,
494             { path => { type => SCALAR | ARRAYREF },
495             follow => 0,
496             absolute => 0,
497             }
498             );
499 5         52 my %new;
500              
501 5         22 @new{qw/ path_remaining absolute follow /}
502             = $self->_split_path( @par{qw/ path absolute follow /} );
503 5         12 $new{state} = 'nextdir';
504 5 100       16 $new{resulting_path} = $new{absolute} ? '/' : '';
505              
506 5         8 unshift @{ $self->{state_stack} }, \%new;
  5         20  
507              
508 5 100 100     35 $self->_pop_state if !$self->{state} || ( $self->{state} eq 'finished' );
509             }
510              
511             sub prepend {
512 2     2 1 957 my $self = shift;
513              
514 2         13 my %par = validate(
515             @_,
516             { path => { type => SCALAR | ARRAYREF },
517             follow => 0,
518             absolute => 0,
519             }
520             );
521              
522 2         16 $self->_push_state;
523              
524 2         8 my ( $pr, $abs, $fol )
525             = $self->_split_path( @par{qw/ path absolute follow /} );
526 2         5 $self->{path_remaining} = $pr;
527 2         4 $self->{absolute} = $abs;
528 2         4 $self->{follow} = $fol;
529 2 50       5 $self->{resulting_path} = $self->{absolute} ? '/' : '';
530 2         7 $self->_set_state( state => 'nextdir' );
531             }
532              
533             sub _split_path {
534 35     35   59 my $self = shift;
535              
536 35         142 my ( $path, $abs, $follow ) = validate_pos( @_, 0, 0, 0 );
537              
538 35 100 100     355 return ( $path, $abs, $follow ) if !defined($path) || ref $path;
539              
540 29         110 $path =~ s!//!/!g;
541 29         81 $abs = $path =~ s!^/!!;
542 29         74 $path =~ s!^\./!/!;
543 29         136 my @out = split m(/), $path, -1; #/ (syntax highlighting)
544 29 100       95 shift @out if $out[0] eq '';
545 29 100       84 pop @out if $out[-1] eq '';
546              
547 29         152 ( \@out, $abs, $follow );
548             }
549              
550             sub _set_state {
551 3283     3283   4002 my $self = shift;
552              
553 3283         22225 my %par = validate(
554             @_,
555             { state => { type => SCALAR },
556             dir => { type => GLOBREF | CODEREF, optional => 1 },
557             wildcard => 0,
558             }
559             );
560 3283         47425 $self->{$_} = $par{$_} for keys %par;
561             }
562              
563             sub _push_state {
564 1416     1416   1720 my $self = shift;
565              
566 1416         4857 $self->_debug( "Push state: "
567             . $self->{state}
568             . " resulting_path: "
569             . $self->{resulting_path}
570             . " Wildcard: "
571             . ( $self->{wildcard} || '' )
572             . " path_remaining: "
573 1416   100     5783 . join( '/', @{ $self->{path_remaining} } )
574             . "\n" );
575 1416         3254 push @{ $self->{state_stack} }, {
  1416         4517  
576             map {
577 1416         1864 $_, ( ref( $self->{$_} ) eq 'ARRAY' )
578 5664 100       20675 ? [ @{ $self->{$_} } ]
579             : $self->{$_}
580             } qw/ state path_remaining dir resulting_path /
581             };
582             }
583              
584             sub _pop_state {
585 1454     1454   2051 my $self = shift;
586              
587 1454   100     3538 $self->{state_stack} ||= [];
588 1454         3256 my $newstate
589 1421         2445 = @{ $self->{state_stack} }
590 1454 100       1557 ? pop( @{ $self->{state_stack} } )
591             : { state => 'finished', dir => undef };
592 1454         16727 $self->{$_} = $newstate->{$_} for keys %$newstate;
593 1454         5262 $self->_debug( "Pop state to "
594             . $self->{state}
595             . " resulting_path: "
596             . $self->{resulting_path}
597             . " Wildcard: "
598             . ( $self->{wildcard} || '' )
599             . " path_remaining: "
600 1454   100     7411 . join( '/', @{ $self->{path_remaining} } )
601             . "\n" );
602             }
603              
604             sub _state_initial {
605 29     29   144 my $self = shift;
606              
607 29 100       115 $self->{resulting_path} = $self->{absolute} ? '/' : '';
608 29         34 $self->{path_remaining} = [ @{ $self->{path} } ];
  29         124  
609              
610 29         82 $self->_set_state( state => 'nextdir' );
611             }
612              
613             sub _state_finished {
614 34     34   61 my $self = shift;
615              
616 34         339 $self->{retval} = undef; # Autovivification optimises this away :(
617             }
618              
619             sub _state_nextdir {
620 3321     3321   4302 my $self = shift;
621              
622 3321 100       3251 unless ( @{ $self->{path_remaining} } ) {
  3321         9143  
623 478         870 $self->_debug("Exhaused path\n");
624 478         608 my $re = $self->{match};
625 478 100 100     6948 $self->{retval} = $self->_derived
626             if ( -e $self->{resulting_path} )
627             && ( $self->{resulting_path} =~ /$re/ );
628 478         975 $self->_pop_state;
629 478         1904 return;
630             }
631              
632 2843         4194 my $pathcomp = shift @{ $self->{path_remaining} };
  2843         5402  
633 2843         8158 $self->_debug("Path component '$pathcomp'\n");
634 2843 100       12069 if ( $pathcomp eq '' ) {
    100          
635 698         1092 my $order = $self->{ellipsis_order};
636 698 100       1884 $self->_set_state(
637             state => ( $order eq 'inside-out' ) ? 'nextdir' : 'ellipsis' );
638 698 100       1953 if ( $order ne 'breadth-first' ) {
639 692         1410 $self->_push_state;
640 692 100       2801 $self->_set_state(
641             state => ( $order eq 'inside-out' )
642             ? 'ellipsis'
643             : 'nextdir'
644             );
645             }
646              
647             }
648             elsif ( $pathcomp !~ /\?|\*/ ) {
649 1185         1959 $self->{resulting_path} .= $pathcomp;
650 1185         8719 my $rp = $self->{resulting_path};
651 1185 100 100     4012 if ( exists( $self->{exclude} ) && $rp =~ /$self->{exclude}/ ) {
652 10         31 $self->_pop_state;
653 10         33 return;
654             }
655 1175         15313 my $sl = readlink $rp;
656 1175 100       5862 if ($sl) {
657 5         114 my $slpath = File::Spec->rel2abs( $sl, $rp );
658 5 100       23 if ( exists $self->{seen_symlink}{$slpath} ) {
659 2         6 $self->_pop_state;
660 2         7 return;
661             }
662 3         10 $self->{seen_symlink}{$slpath}++;
663 3 100       13 $self->{path_remaining} = [] unless $self->{follow};
664             }
665 1173 100       21345 $self->{resulting_path} .= '/' if -d $self->{resulting_path};
666             }
667             else {
668 960         1089 my $wcdir;
669 960 100 100     20983 if ( !opendir $wcdir, $self->{resulting_path} || '.' ) {
670 543         1220 $self->_pop_state;
671 543         2330 return;
672             }
673 417         809 my $wc_re = quotemeta $pathcomp;
674 417         728 $wc_re =~ s!((?:\\\?)+)!'(.{'.(length($1)/2).'})'!eg;
  3         26  
675 417         1353 $wc_re =~ s!\\\*!([^/]*)!g;
676 417 100       8956 my %newstate = (
677             state => 'wildcard',
678             dir => $wcdir,
679             wildcard => $self->{case_insensitive}
680             ? qr(^$wc_re$)i
681             : qr(^$wc_re$)
682             );
683 417 100       1190 if ( $self->{sort} ) {
684 1171 100 100     10754 my @wcmatch = grep {
    100          
685 270         3658 ( $_ ne '.' )
686             && ( $_ ne '..' )
687             && ( $self->{case_insensitive} ? /$wc_re/i : /$wc_re/ )
688             } readdir($wcdir);
689              
690 270 50       1125 if ( $^O =~ /vms/i ) {
691 0         0 s/\.dir$// for @wcmatch;
692             }
693              
694             @wcmatch
695 1         4 = ( ref( $self->{sort} ) eq 'CODE' )
696 1         3 ? ( sort { &{ $self->{sort} }( $a, $b ) } @wcmatch )
  471         790  
697             : $self->{case_insensitive}
698 270 100       1354 ? ( sort { lc($a) cmp lc($b) } @wcmatch )
    100          
699             : ( sort @wcmatch );
700 270 100       619 if ( $self->{exclude} ) {
701 119         599 @wcmatch = grep {
702 66         107 ( $self->{path_remaining} . $_ )
703             !~ /$self->{exclude}/
704             } @wcmatch;
705             }
706 270         400 $newstate{state} = 'wildcard_sorted';
707             $newstate{dir} = sub {
708 782   100 782   2326 my $fil = ( shift @wcmatch ) || '';
709 782         1546 my $rem = join ' ', @wcmatch;
710 782         2503 $self->_debug("wildcard_sorted yields $fil remaining $rem\n");
711 782         1683 return $fil;
712 270         1977 };
713             }
714 417         1582 $self->_set_state(%newstate);
715             }
716             }
717              
718             sub _state_wildcard {
719 351     351   443 my $self = shift;
720              
721 351         455 my $fil = '.';
722 351         473 my $re = $self->{wildcard};
723 351   100     861 while (
      100        
      33        
      66        
724             ( $fil eq '.' )
725             || ( $fil eq '..' )
726             || ( $fil !~ /$re/ )
727             || ( exists( $self->{exclude} )
728             && ( $self->{resulting_path} . $fil =~ /$self->{exclude}/ ) )
729             )
730             {
731 768         3669 $fil = readdir $self->{dir};
732 768 100       5695 return $self->_pop_state unless defined $fil;
733             }
734 204 50       645 $fil =~ s/.dir$// if $^O =~ /vms/i;
735 204         391 $self->_push_state;
736 204         358 unshift @{ $self->{path_remaining} }, $fil;
  204         488  
737 204         473 $self->_set_state( state => 'nextdir' );
738             }
739              
740             sub _state_wildcard_sorted {
741 782     782   1025 my $self = shift;
742              
743 782         1018 my $fil = &{ $self->{dir} };
  782         1485  
744 782 100       1904 return $self->_pop_state unless $fil;
745 512         970 $self->_push_state;
746 512         1000 unshift @{ $self->{path_remaining} }, $fil;
  512         1554  
747 512         1581 $self->_set_state( state => 'nextdir' );
748             }
749              
750             sub _state_ellipsis {
751 698     698   1003 my $self = shift;
752              
753 698 100       1442 if ( $self->{ellipsis_order} eq 'breadth-first' ) {
754 6         7 unshift @{ $self->{path_remaining} }, '*', '';
  6         14  
755 6         13 $self->_set_state( state => 'nextdir' );
756 6         13 $self->_push_state;
757 6         10 splice @{ $self->{path_remaining} }, 1, 1;
  6         29  
758             }
759             else {
760 692         762 unshift @{ $self->{path_remaining} }, '*', '';
  692         2126  
761 692         1672 $self->_set_state( state => 'nextdir' );
762             }
763             }
764              
765             1; #this line is important and will help the module return a true value
766             __END__