package File::Glob;
use strict;
-our($VERSION, @ISA, @EXPORT_OK, @EXPORT_FAIL, %EXPORT_TAGS,
- $AUTOLOAD, $DEFAULT_FLAGS);
+our($VERSION, @ISA, @EXPORT_OK, @EXPORT_FAIL, %EXPORT_TAGS, $DEFAULT_FLAGS);
require XSLoader;
+use feature 'switch';
@ISA = qw(Exporter);
GLOB_NOSPACE
GLOB_QUOTE
GLOB_TILDE
- glob
bsd_glob
+ glob
) ],
);
+$EXPORT_TAGS{bsd_glob} = [@{$EXPORT_TAGS{glob}}];
+pop @{$EXPORT_TAGS{bsd_glob}}; # no "glob"
@EXPORT_OK = (@{$EXPORT_TAGS{'glob'}}, 'csh_glob');
-$VERSION = '1.09';
+$VERSION = '1.14';
sub import {
require Exporter;
- my $i = 1;
- while ($i < @_) {
- if ($_[$i] =~ /^:(case|nocase|globally)$/) {
- splice(@_, $i, 1);
- $DEFAULT_FLAGS &= ~GLOB_NOCASE() if $1 eq 'case';
- $DEFAULT_FLAGS |= GLOB_NOCASE() if $1 eq 'nocase';
- if ($1 eq 'globally') {
- local $^W;
+ local $Exporter::ExportLevel = $Exporter::ExportLevel + 1;
+ Exporter::import(grep {
+ my $passthrough;
+ given ($_) {
+ $DEFAULT_FLAGS &= ~GLOB_NOCASE() when ':case';
+ $DEFAULT_FLAGS |= GLOB_NOCASE() when ':nocase';
+ when (':globally') {
+ no warnings 'redefine';
*CORE::GLOBAL::glob = \&File::Glob::csh_glob;
}
- next;
+ if ($_ eq ':bsd_glob') {
+ no strict; *{caller."::glob"} = \&bsd_glob_override;
+ }
+ $passthrough = 1;
}
- ++$i;
- }
- goto &Exporter::import;
-}
-
-sub AUTOLOAD {
- # This AUTOLOAD is used to 'autoload' constants from the constant()
- # XS function.
-
- my $constname;
- ($constname = $AUTOLOAD) =~ s/.*:://;
- my ($error, $val) = constant($constname);
- if ($error) {
- require Carp;
- Carp::croak($error);
- }
- eval "sub $AUTOLOAD { $val }";
- goto &$AUTOLOAD;
+ $passthrough;
+ } @_);
}
XSLoader::load();
-sub GLOB_CSH () {
- GLOB_BRACE()
- | GLOB_NOMAGIC()
- | GLOB_QUOTE()
- | GLOB_TILDE()
- | GLOB_ALPHASORT()
-}
-
$DEFAULT_FLAGS = GLOB_CSH();
if ($^O =~ /^(?:MSWin32|VMS|os2|dos|riscos)$/) {
$DEFAULT_FLAGS |= GLOB_NOCASE();
}
-sub bsd_glob {
- my ($pat,$flags) = @_;
- $flags = $DEFAULT_FLAGS if @_ < 2;
- return doglob($pat,$flags);
-}
-
# File::Glob::glob() is deprecated because its prototype is different from
# CORE::glob() (use bsd_glob() instead)
sub glob {
goto &bsd_glob;
}
-## borrowed heavily from gsar's File::DosGlob
-my %iter;
-my %entries;
-
-sub csh_glob {
- my $pat = shift;
- my $cxix = shift;
- my @pat;
-
- # glob without args defaults to $_
- $pat = $_ unless defined $pat;
-
- # extract patterns
- $pat =~ s/^\s+//; # Protect against empty elements in
- $pat =~ s/\s+$//; # things like < *.c> and <*.c >.
- # These alone shouldn't trigger ParseWords.
- if ($pat =~ /\s/) {
- # XXX this is needed for compatibility with the csh
- # implementation in Perl. Need to support a flag
- # to disable this behavior.
- require Text::ParseWords;
- @pat = Text::ParseWords::parse_line('\s+',0,$pat);
- }
-
- # assume global context if not provided one
- $cxix = '_G_' unless defined $cxix;
- $iter{$cxix} = 0 unless exists $iter{$cxix};
-
- # if we're just beginning, do it all first
- if ($iter{$cxix} == 0) {
- if (@pat) {
- $entries{$cxix} = [ map { doglob($_, $DEFAULT_FLAGS) } @pat ];
- }
- else {
- $entries{$cxix} = [ doglob($pat, $DEFAULT_FLAGS) ];
- }
- }
-
- # chuck it all out, quick or slow
- if (wantarray) {
- delete $iter{$cxix};
- return @{delete $entries{$cxix}};
- }
- else {
- if ($iter{$cxix} = scalar @{$entries{$cxix}}) {
- return shift @{$entries{$cxix}};
- }
- else {
- # return undef for EOL
- delete $iter{$cxix};
- delete $entries{$cxix};
- return undef;
- }
- }
-}
-
1;
__END__
=head1 SYNOPSIS
- use File::Glob ':glob';
+ use File::Glob ':bsd_glob';
@list = bsd_glob('*.[ch]');
$homedir = bsd_glob('~gnat', GLOB_TILDE | GLOB_ERR);
Note that they don't share the same prototype--CORE::glob() only accepts
a single argument. Due to historical reasons, CORE::glob() will also
split its argument on whitespace, treating it as multiple patterns,
-whereas bsd_glob() considers them as one pattern.
+whereas bsd_glob() considers them as one pattern. But see C<:bsd_glob>
+under L</EXPORTS>, below.
=head2 META CHARACTERS
The metanotation C<a{b,c,d}e> is a shorthand for C<abe ace ade>. Left to
right order is preserved, with results of matches being sorted separately
-at a low level to preserve this order. As a special case C<{>, C<}>, and
+at a low level to preserve this order. As a special case C<{>, C<}>, and
C<{}> are passed undisturbed.
+=head2 EXPORTS
+
+The C<:bsd_glob> export tag exports bsd_glob() and the constants listed
+below. It also overrides glob() in the calling package with one that
+behaves like bsd_glob() with regard to spaces (the space is treated as part
+of a file name), but supports iteration in scalar context; i.e., it
+preserves the core function's feature of returning the next item each time
+it is called.
+
+The C<:glob> tag, now discouraged, is the old version of C<:bsd_glob>. It
+exports the same constants and functions, but its glob() override does not
+support iteration; it returns the last file name in scalar context. That
+means this will loop forever:
+
+ use File::Glob ':glob';
+ while (my $file = <* copy.txt>) {
+ ...
+ }
+
+The bsd_glob() function and the constants below can be exported
+individually.
+
+The csh_glob() function can also be exported, but you should not use it
+directly unless you really know what you are doing. It splits the pattern
+into words and feeds each one to bsd_glob(). Perl's own glob() function
+uses this internally.
+
=head2 POSIX FLAGS
The POSIX defined flags for bsd_glob() are:
On DOSISH systems, backslash is a valid directory separator character.
In this case, use of backslash as a quoting character (via GLOB_QUOTE)
-interferes with the use of backslash as a directory separator. The
+interferes with the use of backslash as a directory separator. The
best (simplest, most portable) solution is to use forward slashes for
-directory separators, and backslashes for quoting. However, this does
-not match "normal practice" on these systems. As a concession to user
+directory separators, and backslashes for quoting. However, this does
+not match "normal practice" on these systems. As a concession to user
expectation, therefore, backslashes (under GLOB_QUOTE) only quote the
glob metacharacters '[', ']', '{', '}', '-', '~', and backslash itself.
All other backslashes are passed through unchanged.
backslashes, consider using Sarathy's File::DosGlob, which comes with
the standard Perl distribution.
-=item *
-
-Mac OS (Classic) users should note a few differences. Since
-Mac OS is not Unix, when the glob code encounters a tilde glob (e.g.
-~user) and the C<GLOB_TILDE> flag is used, it simply returns that
-pattern without doing any expansion.
-
-Glob on Mac OS is case-insensitive by default (if you don't use any
-flags). If you specify any flags at all and still want glob
-to be case-insensitive, you must include C<GLOB_NOCASE> in the flags.
-
-The path separator is ':' (aka colon), not '/' (aka slash). Mac OS users
-should be careful about specifying relative pathnames. While a full path
-always begins with a volume name, a relative pathname should always
-begin with a ':'. If specifying a volume name only, a trailing ':' is
-required.
-
-The specification of pathnames in glob patterns adheres to the usual Mac
-OS conventions: The path separator is a colon ':', not a slash '/'. A
-full path always begins with a volume name. A relative pathname on Mac
-OS must always begin with a ':', except when specifying a file or
-directory name in the current working directory, where the leading colon
-is optional. If specifying a volume name only, a trailing ':' is
-required. Due to these rules, a glob like E<lt>*:E<gt> will find all
-mounted volumes, while a glob like E<lt>*E<gt> or E<lt>:*E<gt> will find
-all files and directories in the current directory.
-
-Note that updirs in the glob pattern are resolved before the matching begins,
-i.e. a pattern like "*HD:t?p::a*" will be matched as "*HD:a*". Note also,
-that a single trailing ':' in the pattern is ignored (unless it's a volume
-name pattern like "*HD:"), i.e. a glob like E<lt>:*:E<gt> will find both
-directories I<and> files (and not, as one might expect, only directories).
-You can, however, use the C<GLOB_MARK> flag to distinguish (without a file
-test) directory names from file names.
-
-If the C<GLOB_MARK> flag is set, all directory paths will have a ':' appended.
-Since a directory like 'lib:' is I<not> a valid I<relative> path on Mac OS,
-both a leading and a trailing colon will be added, when the directory name in
-question doesn't contain any colons (e.g. 'lib' becomes ':lib:').
-
=back
=head1 SEE ALSO