FastGlob
view release on metacpan or search on metacpan
lib/FastGlob.pm view on Meta::CPAN
use Exporter ();
use Carp qw(carp);
our @ISA = qw(Exporter);
our @EXPORT = qw(glob);
our @EXPORT_OK = qw(dirsep rootpat curdir parentdir hidedotfiles);
# platform specifics â auto-detect Windows defaults
my $IS_WINDOWS = ( $^O eq 'MSWin32' );
our $dirsep = $IS_WINDOWS ? '\\' : '/';
our $rootpat = $IS_WINDOWS ? '[A-Za-z]:' : '\A\Z';
our $curdir = '.';
our $parentdir = '..';
our $hidedotfiles = 1;
our $verbose = 0;
#
# recursively wildcard expand a list of strings
#
sub glob {
my @res;
my $part;
my $found1;
my $out;
my $bracepat = qr(\{([^\{\}]*)\});
# deal with {xxx,yyy,zzz}
@res = ();
$found1 = 1;
while ($found1) {
$found1 = 0;
for (@_) {
if ( m{$bracepat} ) {
foreach $part (split(',',$1)) {
$out = $_;
$out =~ s/$bracepat/$part/;
push(@res, $out);
}
$found1 = 1;
} else {
push(@res, $_);
}
}
@_ = @res;
@res = ();
}
# skip empty patterns â CORE::glob returns nothing for them
@_ = grep { defined $_ && $_ ne '' } @_;
for (@_) {
# check for and do tilde expansion
if ( /^\~([^\Q${dirsep}\E]*)/ ) {
my $usr = $1;
my $usrdir;
if ( $usr eq "" ) {
# ~ alone: try getpwuid, fall back to $HOME / $USERPROFILE
$usrdir = eval { (getpwuid($<))[7] };
if ( !defined $usrdir ) {
$usrdir = defined $ENV{HOME} ? $ENV{HOME} : $ENV{USERPROFILE};
}
} else {
# ~user: try getpwnam (not available on Windows)
$usrdir = eval { (getpwnam($usr))[7] };
}
if ( defined $usrdir && $usrdir ne "" ) {
s/^\~\Q$usr\E/$usrdir/;
}
# Always keep the entry â if expansion fails, preserve the
# original pattern unchanged (consistent with CORE::glob)
push(@res, $_);
} else {
push(@res, $_);
}
}
@_ = @res;
@res = ();
for (@_) {
# if there's no wildcards, just return it
unless (/(?<!\\)[*?\[\]{}]/) {
push (@res, $_);
next;
}
# Split into directory components FIRST, before regex transformation.
# This prevents regex escape sequences (e.g. \.) from being confused
# with the directory separator on Windows where $dirsep is \.
# On Windows, accept both / and \ as path separators in patterns.
my @comps;
if ( $IS_WINDOWS ) {
@comps = split(m{[/\\]});
} else {
@comps = split(/\Q$dirsep\E/);
}
# Check for root pattern before transforming components
my $is_rooted = ($comps[0] =~ /($rootpat)/);
my $root_prefix = $is_rooted ? $1 : undef;
# Transform each component into a regex
for my $comp (@comps) {
if ( $comp =~ /(?<!\\)[*?\[\]]/ ) {
# Wildcard component: convert glob pattern to regex
# escape regex metacharacters that are not glob syntax
$comp =~ s/([+.|(){}\$])/\\$1/g;
# convert POSIX [!...] negation to regex [^...]
# Only convert when there are chars between ! and ] (avoid [!] -> [^] which is invalid)
$comp =~ s/\[!(?=[^\]]+\])/[^/g;
# handle * and ?
$comp =~ s/(?<!\\)(\*)/.*/g;
$comp =~ s/(?<!\\)(\?)/./g;
} else {
# Literal component: escape regex metacharacters
lib/FastGlob.pm view on Meta::CPAN
}
}
return @res;
}
1;
__END__
=pod
=encoding UTF-8
=head1 NAME
FastGlob - A faster glob() implementation
=head1 VERSION
version 1.6
=head1 SYNOPSIS
use FastGlob qw(glob);
my @list = glob('*.c');
=head1 DESCRIPTION
This module implements globbing in perl, rather than forking a csh.
This is faster than the built-in glob() call, and more robust (on
many platforms, csh chokes on C<echo *> if too many files are in the
directory.)
There are several module-local variables that control platform-specific
behavior. On Windows (C<$^O eq 'MSWin32'>), these are automatically set
to appropriate values. On other platforms, UNIX defaults are used.
You can override them after loading the module if needed.
# UNIX defaults (auto-detected):
$FastGlob::dirsep = '/'; # directory path separator
$FastGlob::rootpat = '\A\Z'; # root directory prefix pattern
$FastGlob::curdir = '.'; # name of current directory in dir
$FastGlob::parentdir = '..'; # name of parent directory in dir
$FastGlob::hidedotfiles = 1; # hide filenames starting with .
# Windows defaults (auto-detected on MSWin32):
$FastGlob::dirsep = '\\'; # directory path separator
$FastGlob::rootpat = '[A-Za-z]:'; # <Drive letter><colon> pattern
$FastGlob::curdir = '.'; # name of current directory in dir
$FastGlob::parentdir = '..'; # name of parent directory in dir
$FastGlob::hidedotfiles = 1; # hide filenames starting with .
For classic MacOS you would set:
$FastGlob::dirsep = ':'; # directory path separator
$FastGlob::rootpat = '\A\Z'; # root directory prefix pattern
$FastGlob::curdir = '.'; # name of current directory in dir
$FastGlob::parentdir = '..'; # name of parent directory in dir
$FastGlob::hidedotfiles = 0; # hide filenames starting with .
Tilde expansion (C<~> and C<~user>) uses C<getpwuid>/C<getpwnam> on UNIX.
On Windows, C<~> falls back to C<$HOME> or C<$USERPROFILE>.
=head1 INSTALLATION
Copy this module to the Perl 5 Library directory.
=head1 AUTHOR
Marc Mengel <mengel@fnal.gov>
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 1999 by Marc Mengel.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut
( run in 0.600 second using v1.01-cache-2.11-cpan-99c4e6809bf )