@@ -1,12 +1,10 @@
# $Id$
-1.09 - Sat Oct 4 12:48:06 2008
- * Now requires 5.008. This probably still works on 5.6.2, so
- if you want to use that, just don't run the tests since the
- way I mocked a few things doesn't work in 5.6.
+1.10 - Fri Jan 3 14:12:45 2014
+ * Get rid of MYMETA
-1.08 - Sat Sep 27 03:57:40 2008
- * fixed find_by_directory_contains, which didn't do anything right.
+1.08 - Wed Jul 18 18:24:46 2012
+ * Add the File::Spec::Functions prereq (RT #39826)
1.07 - Fri Nov 9 05:51:33 2007
* updates for the move from CVS to SVN, and latest kwalitee
@@ -1,9 +1,10 @@
Changes
examples/README
-lib/Closures.pm
+lib/File/Find/Closures.pm
LICENSE
Makefile.PL
MANIFEST
+MANIFEST.SKIP
README
t/compile.t
t/find_by_directory_contains.t
@@ -20,4 +21,5 @@ t/pod.t
t/pod_coverage.t
t/test_manifest
t/unimplemented.t
-META.yml Module meta-data (added by MakeMaker)
+META.yml Module YAML meta-data (added by MakeMaker)
+META.json Module JSON meta-data (added by MakeMaker)
@@ -0,0 +1,64 @@
+
+#!start included /usr/local/perls/perl-5.18.1/lib/5.18.1/ExtUtils/MANIFEST.SKIP
+# Avoid version control files.
+\bRCS\b
+\bCVS\b
+\bSCCS\b
+,v$
+\B\.svn\b
+\B\.git\b
+\B\.gitignore\b
+\b_darcs\b
+\B\.cvsignore$
+
+# Avoid VMS specific MakeMaker generated files
+\bDescrip.MMS$
+\bDESCRIP.MMS$
+\bdescrip.mms$
+
+# Avoid Makemaker generated and utility files.
+\bMANIFEST\.bak
+\bMakefile$
+\bblib/
+\bMakeMaker-\d
+\bpm_to_blib\.ts$
+\bpm_to_blib$
+\bblibdirs\.ts$ # 6.18 through 6.25 generated this
+
+# Avoid Module::Build generated and utility files.
+\bBuild$
+\b_build/
+\bBuild.bat$
+\bBuild.COM$
+\bBUILD.COM$
+\bbuild.com$
+
+# Avoid temp and backup files.
+~$
+\.old$
+\#$
+\b\.#
+\.bak$
+\.tmp$
+\.#
+\.rej$
+
+# Avoid OS-specific files/dirs
+# Mac OSX metadata
+\B\.DS_Store
+# Mac OSX SMB mount metadata files
+\B\._
+
+# Avoid Devel::Cover and Devel::CoverX::Covered files.
+\bcover_db\b
+\bcovered\b
+
+# Avoid MYMETA files
+^MYMETA\.
+#!end included /usr/local/perls/perl-5.18.1/lib/5.18.1/ExtUtils/MANIFEST.SKIP
+
+
+\.travis\.yml
+\.releaserc
+\.lwpcookies
+^File-.*
@@ -0,0 +1,30 @@
+{
+ "abstract" : "functions you can use with File::Find",
+ "author" : [
+ "brian d foy <bdfoy@cpan.org>"
+ ],
+ "dynamic_config" : 1,
+ "generated_by" : "ExtUtils::MakeMaker version 6.62, CPAN::Meta::Converter version 2.112150",
+ "license" : [
+ "perl_5"
+ ],
+ "meta-spec" : {
+ "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec",
+ "version" : "2"
+ },
+ "name" : "File-Find-Closures",
+ "no_index" : {
+ "directory" : [
+ "t",
+ "inc"
+ ]
+ },
+ "release_status" : "stable",
+ "resources" : {
+ "repository" : {
+ "type" : "git",
+ "web" : "https://github.com/briandfoy/file-find-closures"
+ }
+ },
+ "version" : "1.10"
+}
@@ -1,14 +1,19 @@
---- #YAML:1.0
-name: File-Find-Closures
-version: 1.09
-abstract: functions you can use with File::Find
-license: perl
-author:
- - brian d foy <bdfoy@cpan.org>
-generated_by: ExtUtils::MakeMaker version 6.44
-distribution_type: module
-requires:
- File::Find: 0
+---
+abstract: 'functions you can use with File::Find'
+author:
+ - 'brian d foy <bdfoy@cpan.org>'
+build_requires: {}
+dynamic_config: 1
+generated_by: 'ExtUtils::MakeMaker version 6.62, CPAN::Meta::Converter version 2.112150'
+license: perl
meta-spec:
- url: http://module-build.sourceforge.net/META-spec-v1.3.html
- version: 1.3
+ url: http://module-build.sourceforge.net/META-spec-v1.4.html
+ version: 1.4
+name: File-Find-Closures
+no_index:
+ directory:
+ - t
+ - inc
+resources:
+ repository: https://github.com/briandfoy/file-find-closures
+version: 1.10
@@ -1,31 +1,33 @@
-# $Id$
-use ExtUtils::MakeMaker;
+use ExtUtils::MakeMaker 6.48;
require 5.008;
-eval "use Test::Manifest 1.14";
+eval "use Test::Manifest 1.21";
WriteMakefile(
'NAME' => 'File::Find::Closures',
'ABSTRACT' => 'functions you can use with File::Find',
- 'VERSION_FROM' => 'lib/Closures.pm',
+ 'VERSION_FROM' => 'lib/File/Find/Closures.pm',
'LICENSE' => 'perl',
'AUTHOR' => 'brian d foy <bdfoy@cpan.org>',
'PREREQ_PM' => {
- 'File::Find' => '0',
+ 'File::Find' => '0',
+ 'File::Spec::Functions' => '3.33',
},
- 'PM' => {
- 'lib/Closures.pm' => '$(INST_LIBDIR)/Closures.pm',
- },
-
- 'MAN3PODS' => {
- 'lib/Closures.pm' => '$(INST_MAN3DIR)/File::Find::Closures.3',
+ 'META_MERGE' => {
+ 'meta-spec' => { version => 2 },
+ resources => {
+ repository => {
+ type => 'git',
+ url => 'git@github.com:briandfoy/file-find-closures.git',
+ web => 'https://github.com/briandfoy/file-find-closures',
+ },
+ },
},
clean => { FILES => q|File-Find-Closures-*| },
-
);
@@ -1,5 +1,3 @@
-$Id$
-
You can install this using in the usual Perl fashion
perl Makefile.PL
@@ -15,7 +13,7 @@ the file, you can read it with perldoc.
If you want to read it before you install it, you can use
perldoc directly on the module file.
- perldoc lib/Closures.pm
+ perldoc lib/File/Find/Closures.pm
This module is also in Github:
@@ -1,474 +0,0 @@
-# $Id$
-package File::Find::Closures;
-use strict;
-
-use warnings;
-no warnings;
-
-use vars qw( $VERSION @EXPORT_OK %EXPORT_TAGS );
-
-use Carp qw(carp croak);
-use Exporter;
-use File::Basename qw(dirname);
-use File::Spec::Functions qw(canonpath no_upwards);
-use UNIVERSAL qw(isa);
-
-$VERSION = '1.09';
-
-@EXPORT_OK = qw(
- find_regular_files
- find_by_min_size
- find_by_max_size
- find_by_zero_size
- find_by_directory_contains
- find_by_name
- find_by_regex
- find_by_owner
- find_by_group
- find_by_executable
- find_by_writeable
- find_by_umask
- find_by_modified_before
- find_by_modified_after
- find_by_created_before
- find_by_created_after
- );
-
-%EXPORT_TAGS = (
- all => \@EXPORT_OK
- );
-
-sub _unimplemented { croak "Unimplemented function!" }
-
-=head1 NAME
-
-File::Find::Closures - functions you can use with File::Find
-
-=head1 SYNOPSIS
-
- use File::Find;
- use File::Find::Closures qw(:all);
-
- my( $wanted, $list_reporter ) = find_by_name( qw(README) );
-
- File::Find::find( $wanted, @directories );
- File::Find::find( { wanted => $wanted, ... }, @directories );
-
- my @readmes = $list_reporter->();
-
-=head1 DESCRIPTION
-
-I wrote this module as an example of both using closures and using
-File::Find. Students are always asking me what closures are good
-for, and here's some examples. The functions mostly stand alone (i.e.
-they don't need the rest of the module), so rather than creating a
-dependency in your code, just lift the parts you want).
-
-When I use File::Find, I have two headaches---coming up with the
-\&wanted function to pass to find(), and acculumating the files.
-
-This module provides the \&wanted functions as a closures that I can
-pass directly to find(). Actually, for each pre-made closure, I
-provide a closure to access the list of files too, so I don't have to
-create a new array to hold the results.
-
-The filenames are the full path to the file as reported by File::Find.
-
-Unless otherwise noted, the reporter closure returns a list of the
-filenames in list context and an anonymous array that is a copy (not a
-reference) of the original list. The filenames have been normalized
-by File::Spec::canonfile unless otherwise noted. The list of files
-has been processed by File::Spec::no_upwards so that "." and ".." (or
-their equivalents) do not show up in the list.
-
-
-=head2 The closure factories
-
-Each factory returns two closures. The first one is for find(),
-and the second one is the reporter.
-
-=over 4
-
-=item find_regular_files();
-
-Find all regular files.
-
-=cut
-
-sub find_regular_files
- {
- my @files = ();
-
- sub { push @files, canonpath( $File::Find::name ) if -f $_ },
- sub { @files = no_upwards( @files ); wantarray ? @files : [ @files ] }
- }
-
-=item find_by_min_size( SIZE );
-
-Find files whose size is equal to or greater than SIZE bytes.
-
-=cut
-
-sub find_by_min_size
- {
- my $min = shift;
-
- my @files = ();
-
- sub { push @files, canonpath( $File::Find::name ) if -s $_ >= $min },
- sub { @files = no_upwards( @files ); wantarray ? @files : [ @files ] }
- }
-
-=item find_by_max_size( SIZE );
-
-Find files whose size is equal to or less than SIZE bytes.
-
-=cut
-
-sub find_by_max_size
- {
- my $min = shift;
-
- my @files = ();
-
- sub { push @files, canonpath( $File::Find::name ) if -s $_ <= $min },
- sub { @files = no_upwards( @files ); wantarray ? @files : [ @files ] }
- }
-
-=item find_by_zero_size();
-
-Find files whose size is equal to 0 bytes.
-
-=cut
-
-sub find_by_zero_size
- {
- my $min = shift;
-
- my @files = ();
-
- sub { push @files, canonpath( $File::Find::name ) if -s $_ == 0 },
- sub { @files = no_upwards( @files ); wantarray ? @files : [ @files ] }
- }
-
-=item find_by_directory_contains( @names );
-
-Find directories which contain files with the same name
-as any of the values in @names.
-
-=cut
-
-sub find_by_directory_contains
- {
- my @contains = @_;
- my %contains = map { $_, 1 } @contains;
-
- my %files = ();
-
- sub {
- return unless exists $contains{$_};
- my $dir = dirname( canonpath( $File::Find::name ) );
-
- $files{ $dir }++;
- },
-
-
- sub { wantarray ? ( keys %files ) : [ keys %files ] }
- }
-
-=item find_by_name( @names );
-
-Find files with the names in @names. The result is the name returned
-by $File::Find::name normalized by File::Spec::canonfile().
-
-In list context, it returns the list of files. In scalar context,,
-it returns an anonymous array.
-
-This function does not use no_updirs, so if you ask for "." or "..",
-that's what you get.
-
-=cut
-
-sub find_by_name
- {
- my %hash = map { $_, 1 } @_;
- my @files = ();
-
- sub { push @files, canonpath( $File::Find::name ) if exists $hash{$_} },
- sub { wantarray ? @files : [ @files ] }
- }
-
-=item find_by_regex( REGEX );
-
-Find files whose name match REGEX.
-
-This function does not use no_updirs, so if you ask for "." or "..",
-that's what you get.
-
-=cut
-
-sub find_by_regex
- {
- require File::Spec::Functions;
- require Carp;
- require UNIVERSAL;
-
- my $regex = shift;
-
- unless( UNIVERSAL::isa( $regex, ref qr// ) )
- {
- croak "Argument must be a regular expression";
- }
-
- my @files = ();
-
- sub { push @files,
- File::Spec::Functions::canonpath( $File::Find::name ) if m/$regex/ },
- sub { wantarray ? @files : [ @files ] }
- }
-
-=item find_by_owner( OWNER_NAME | OWNER_UID );
-
-Find files that are owned by the owner with the name OWNER_NAME.
-You can also use the owner's UID.
-
-=cut
-
-sub find_by_owner
- {
- my $id = getpwnam($_[0]);
- $id = $_ unless defined($id);
-
- unless( $id =~ /\d+/ )
- {
- carp "Uid must be numeric of a valid system user name";
- }
-
- return _find_by_stat_part_equal( $id, 4 );
- }
-
-=item find_by_group( GROUP_NAME | GROUP_GID );
-
-Find files that are owned by the owner with the name GROUP_NAME.
-You can also use the group's GID.
-
-=cut
-
-sub find_by_group
- {
- my $id = getgrnam( $_[0] );
- $id = $_ unless defined( $id );
-
- unless( $id =~ /\d+/ )
- {
- carp "Gid must be numeric or a valid system user name";
- }
-
- return _find_by_stat_part_equal( $id, 5 );
- }
-
-=item find_by_executable();
-
-Find files that are executable. This may not work on some operating
-systems (like Windows) unless someone can provide me with an
-alternate version.
-
-=cut
-
-sub find_by_executable
- {
- my @files = ();
- sub { push @files, canonpath( $File::Find::name )
- if -x },
- sub { wantarray ? @files : [ @files ] }
- }
-
-=item find_by_writeable();
-
-Find files that are writable. This may not work on some operating
-systems (like Windows) unless someone can provide me with an
-alternate version.
-
-=cut
-
-sub find_by_writeable
- {
- my @files = ();
- sub { push @files, canonpath( $File::Find::name )
- if -w },
- sub { wantarray ? @files : [ @files ] }
- }
-
-=item find_by_umask( UMASK );
-
-Find files that fit the umask UMASK. The files will not have those
-permissions.
-
-=cut
-
-sub find_by_umask
- {
- my ($mask) = @_;
-
- my @files;
-
- sub { push @files, canonpath( $File::Find::name )
- if ((stat($_))[2] & $mask) == 0},
- sub { wantarray ? @files : [ @files ] }
- }
-
-=item find_by_modified_before( EPOCH_TIME );
-
-Find files modified before EPOCH_TIME, which is in seconds since
-the local epoch (I may need to adjust this for some operating
-systems).
-
-=cut
-
-sub find_by_modified_before
- {
- return _find_by_stat_part_lessthan( $_[0], 9 );
- }
-
-=item find_by_modified_after( EPOCH_TIME );
-
-Find files modified after EPOCH_TIME, which is in seconds since
-the local epoch (I may need to adjust this for some operating
-systems).
-
-=cut
-
-sub find_by_modified_after
- {
- return _find_by_stat_part_greaterthan( $_[0], 9 );
- }
-
-=item find_by_created_before( EPOCH_TIME );
-
-Find files created before EPOCH_TIME, which is in seconds since
-the local epoch (I may need to adjust this for some operating
-systems).
-
-=cut
-
-sub find_by_created_before
- {
- return _find_by_stat_part_lessthan( $_[0], 10 );
- }
-
-=item find_by_created_after( EPOCH_TIME );
-
-Find files created after EPOCH_TIME, which is in seconds since
-the local epoch (I may need to adjust this for some operating
-systems).
-
-=cut
-
-sub find_by_created_after
- {
- return _find_by_stat_part_greaterthan( $_[0], 10 );
- }
-
-sub _find_by_stat_part_equal
- {
- my ($value, $stat_part) = @_;
-
- my @files;
-
- sub { push @files, canonpath( $File::Find::name )
- if (stat($_))[$stat_part] == $value },
- sub { wantarray ? @files : [ @files ] }
- }
-
-sub _find_by_stat_part_lessthan
- {
- my ($value, $stat_part) = @_;
-
- my @files;
-
- sub { push @files, canonpath( $File::Find::name )
- if (stat($_))[$stat_part] < $value },
- sub { wantarray ? @files : [ @files ] }
- }
-
-sub _find_by_stat_part_greaterthan
- {
- my ($value, $stat_part) = @_;
-
- my @files;
-
- sub { push @files, canonpath( $File::Find::name )
- if (stat($_))[$stat_part] > $value },
- sub { wantarray ? @files : [ @files ] }
- }
-
-
-=back
-
-=head1 ADD A CLOSURE
-
-I want to add as many of these little functions as I can, so please
-send me ones that you create!
-
-You can follow the examples in the source code, but here is how you
-should write your closures.
-
-You need to provide both closures. Start of with the basic subroutine
-stub to do this. Create a lexical array in the scope of the subroutine.
-The two closures will share this variable. Create two closures: one
-of give to C<find()> and one to access the lexical array.
-
- sub find_by_foo
- {
- my @args = @_;
-
- my @found = ();
-
- my $finder = sub { push @found, $File::Find::name if ... };
- my $reporter = sub { @found };
-
- return( $finder, $reporter );
- }
-
-The filename should be the full path to the file that you get
-from C<$File::Find::name>, unless you are doing something wierd,
-like C<find_by_directory_contains()>.
-
-Once you have something, send it to me at C<< <bdfoy@cpan.org> >>. You
-must release your code under the Perl Artistic License.
-
-=head1 TO DO
-
-* more functions!
-
-* need input on how things like mod times work on other operating
-systems
-
-=head1 SEE ALSO
-
-L<File::Find>
-
-Randal Schwartz's C<File::Finder>, which does the same task but
-differently.
-
-=head1 SOURCE AVAILABILITY
-
-This module is in Github:
-
- git://github.com/briandfoy/file-find-closures.git
-
-=head1 AUTHOR
-
-brian d foy, C<< <bdfoy@cpan.org> >>
-
-Some functions implemented by Nathan Wagner, C<< <nw@hydaspes.if.org> >>
-
-=head1 COPYRIGHT AND LICENSE
-
-Copyright (c) 2004-2007, brian d foy, All Rights Reserved.
-
-You may redistribute this under the same terms as Perl itself.
-
-=cut
-
-"Kanga and Baby Roo Come to the Forest";
@@ -0,0 +1,473 @@
+package File::Find::Closures;
+use strict;
+
+use warnings;
+no warnings;
+
+use vars qw( $VERSION @EXPORT_OK %EXPORT_TAGS );
+
+use Carp qw(carp croak);
+use Exporter qw(import);
+use File::Basename qw(dirname);
+use File::Spec::Functions qw(canonpath no_upwards);
+use UNIVERSAL qw(isa);
+
+$VERSION = '1.10';
+
+@EXPORT_OK = qw(
+ find_regular_files
+ find_by_min_size
+ find_by_max_size
+ find_by_zero_size
+ find_by_directory_contains
+ find_by_name
+ find_by_regex
+ find_by_owner
+ find_by_group
+ find_by_executable
+ find_by_writeable
+ find_by_umask
+ find_by_modified_before
+ find_by_modified_after
+ find_by_created_before
+ find_by_created_after
+ );
+
+%EXPORT_TAGS = (
+ all => \@EXPORT_OK
+ );
+
+sub _unimplemented { croak "Unimplemented function!" }
+
+=head1 NAME
+
+File::Find::Closures - functions you can use with File::Find
+
+=head1 SYNOPSIS
+
+ use File::Find;
+ use File::Find::Closures qw(:all);
+
+ my( $wanted, $list_reporter ) = find_by_name( qw(README) );
+
+ File::Find::find( $wanted, @directories );
+ File::Find::find( { wanted => $wanted, ... }, @directories );
+
+ my @readmes = $list_reporter->();
+
+=head1 DESCRIPTION
+
+I wrote this module as an example of both using closures and using
+File::Find. Students are always asking me what closures are good
+for, and here's some examples. The functions mostly stand alone (i.e.
+they don't need the rest of the module), so rather than creating a
+dependency in your code, just lift the parts you want).
+
+When I use File::Find, I have two headaches---coming up with the
+\&wanted function to pass to find(), and acculumating the files.
+
+This module provides the \&wanted functions as a closures that I can
+pass directly to find(). Actually, for each pre-made closure, I
+provide a closure to access the list of files too, so I don't have to
+create a new array to hold the results.
+
+The filenames are the full path to the file as reported by File::Find.
+
+Unless otherwise noted, the reporter closure returns a list of the
+filenames in list context and an anonymous array that is a copy (not a
+reference) of the original list. The filenames have been normalized
+by File::Spec::canonfile unless otherwise noted. The list of files
+has been processed by File::Spec::no_upwards so that "." and ".." (or
+their equivalents) do not show up in the list.
+
+
+=head2 The closure factories
+
+Each factory returns two closures. The first one is for find(),
+and the second one is the reporter.
+
+=over 4
+
+=item find_regular_files();
+
+Find all regular files.
+
+=cut
+
+sub find_regular_files
+ {
+ my @files = ();
+
+ sub { push @files, canonpath( $File::Find::name ) if -f $_ },
+ sub { @files = no_upwards( @files ); wantarray ? @files : [ @files ] }
+ }
+
+=item find_by_min_size( SIZE );
+
+Find files whose size is equal to or greater than SIZE bytes.
+
+=cut
+
+sub find_by_min_size
+ {
+ my $min = shift;
+
+ my @files = ();
+
+ sub { push @files, canonpath( $File::Find::name ) if -s $_ >= $min },
+ sub { @files = no_upwards( @files ); wantarray ? @files : [ @files ] }
+ }
+
+=item find_by_max_size( SIZE );
+
+Find files whose size is equal to or less than SIZE bytes.
+
+=cut
+
+sub find_by_max_size
+ {
+ my $min = shift;
+
+ my @files = ();
+
+ sub { push @files, canonpath( $File::Find::name ) if -s $_ <= $min },
+ sub { @files = no_upwards( @files ); wantarray ? @files : [ @files ] }
+ }
+
+=item find_by_zero_size();
+
+Find files whose size is equal to 0 bytes.
+
+=cut
+
+sub find_by_zero_size
+ {
+ my $min = shift;
+
+ my @files = ();
+
+ sub { push @files, canonpath( $File::Find::name ) if -s $_ == 0 },
+ sub { @files = no_upwards( @files ); wantarray ? @files : [ @files ] }
+ }
+
+=item find_by_directory_contains( @names );
+
+Find directories which contain files with the same name
+as any of the values in @names.
+
+=cut
+
+sub find_by_directory_contains
+ {
+ my @contains = @_;
+ my %contains = map { $_, 1 } @contains;
+
+ my %files = ();
+
+ sub {
+ return unless exists $contains{$_};
+ my $dir = dirname( canonpath( $File::Find::name ) );
+
+ $files{ $dir }++;
+ },
+
+
+ sub { wantarray ? ( keys %files ) : [ keys %files ] }
+ }
+
+=item find_by_name( @names );
+
+Find files with the names in @names. The result is the name returned
+by $File::Find::name normalized by File::Spec::canonfile().
+
+In list context, it returns the list of files. In scalar context,,
+it returns an anonymous array.
+
+This function does not use no_updirs, so if you ask for "." or "..",
+that's what you get.
+
+=cut
+
+sub find_by_name
+ {
+ my %hash = map { $_, 1 } @_;
+ my @files = ();
+
+ sub { push @files, canonpath( $File::Find::name ) if exists $hash{$_} },
+ sub { wantarray ? @files : [ @files ] }
+ }
+
+=item find_by_regex( REGEX );
+
+Find files whose name match REGEX.
+
+This function does not use no_updirs, so if you ask for "." or "..",
+that's what you get.
+
+=cut
+
+sub find_by_regex
+ {
+ require File::Spec::Functions;
+ require Carp;
+ require UNIVERSAL;
+
+ my $regex = shift;
+
+ unless( UNIVERSAL::isa( $regex, ref qr// ) )
+ {
+ croak "Argument must be a regular expression";
+ }
+
+ my @files = ();
+
+ sub { push @files,
+ File::Spec::Functions::canonpath( $File::Find::name ) if m/$regex/ },
+ sub { wantarray ? @files : [ @files ] }
+ }
+
+=item find_by_owner( OWNER_NAME | OWNER_UID );
+
+Find files that are owned by the owner with the name OWNER_NAME.
+You can also use the owner's UID.
+
+=cut
+
+sub find_by_owner
+ {
+ my $id = getpwnam($_[0]);
+ $id = $_ unless defined($id);
+
+ unless( $id =~ /\d+/ )
+ {
+ carp "Uid must be numeric of a valid system user name";
+ }
+
+ return _find_by_stat_part_equal( $id, 4 );
+ }
+
+=item find_by_group( GROUP_NAME | GROUP_GID );
+
+Find files that are owned by the owner with the name GROUP_NAME.
+You can also use the group's GID.
+
+=cut
+
+sub find_by_group
+ {
+ my $id = getgrnam( $_[0] );
+ $id = $_ unless defined( $id );
+
+ unless( $id =~ /\d+/ )
+ {
+ carp "Gid must be numeric or a valid system user name";
+ }
+
+ return _find_by_stat_part_equal( $id, 5 );
+ }
+
+=item find_by_executable();
+
+Find files that are executable. This may not work on some operating
+systems (like Windows) unless someone can provide me with an
+alternate version.
+
+=cut
+
+sub find_by_executable
+ {
+ my @files = ();
+ sub { push @files, canonpath( $File::Find::name )
+ if -x },
+ sub { wantarray ? @files : [ @files ] }
+ }
+
+=item find_by_writeable();
+
+Find files that are writable. This may not work on some operating
+systems (like Windows) unless someone can provide me with an
+alternate version.
+
+=cut
+
+sub find_by_writeable
+ {
+ my @files = ();
+ sub { push @files, canonpath( $File::Find::name )
+ if -w },
+ sub { wantarray ? @files : [ @files ] }
+ }
+
+=item find_by_umask( UMASK );
+
+Find files that fit the umask UMASK. The files will not have those
+permissions.
+
+=cut
+
+sub find_by_umask
+ {
+ my ($mask) = @_;
+
+ my @files;
+
+ sub { push @files, canonpath( $File::Find::name )
+ if ((stat($_))[2] & $mask) == 0},
+ sub { wantarray ? @files : [ @files ] }
+ }
+
+=item find_by_modified_before( EPOCH_TIME );
+
+Find files modified before EPOCH_TIME, which is in seconds since
+the local epoch (I may need to adjust this for some operating
+systems).
+
+=cut
+
+sub find_by_modified_before
+ {
+ return _find_by_stat_part_lessthan( $_[0], 9 );
+ }
+
+=item find_by_modified_after( EPOCH_TIME );
+
+Find files modified after EPOCH_TIME, which is in seconds since
+the local epoch (I may need to adjust this for some operating
+systems).
+
+=cut
+
+sub find_by_modified_after
+ {
+ return _find_by_stat_part_greaterthan( $_[0], 9 );
+ }
+
+=item find_by_created_before( EPOCH_TIME );
+
+Find files created before EPOCH_TIME, which is in seconds since
+the local epoch (I may need to adjust this for some operating
+systems).
+
+=cut
+
+sub find_by_created_before
+ {
+ return _find_by_stat_part_lessthan( $_[0], 10 );
+ }
+
+=item find_by_created_after( EPOCH_TIME );
+
+Find files created after EPOCH_TIME, which is in seconds since
+the local epoch (I may need to adjust this for some operating
+systems).
+
+=cut
+
+sub find_by_created_after
+ {
+ return _find_by_stat_part_greaterthan( $_[0], 10 );
+ }
+
+sub _find_by_stat_part_equal
+ {
+ my ($value, $stat_part) = @_;
+
+ my @files;
+
+ sub { push @files, canonpath( $File::Find::name )
+ if (stat($_))[$stat_part] == $value },
+ sub { wantarray ? @files : [ @files ] }
+ }
+
+sub _find_by_stat_part_lessthan
+ {
+ my ($value, $stat_part) = @_;
+
+ my @files;
+
+ sub { push @files, canonpath( $File::Find::name )
+ if (stat($_))[$stat_part] < $value },
+ sub { wantarray ? @files : [ @files ] }
+ }
+
+sub _find_by_stat_part_greaterthan
+ {
+ my ($value, $stat_part) = @_;
+
+ my @files;
+
+ sub { push @files, canonpath( $File::Find::name )
+ if (stat($_))[$stat_part] > $value },
+ sub { wantarray ? @files : [ @files ] }
+ }
+
+
+=back
+
+=head1 ADD A CLOSURE
+
+I want to add as many of these little functions as I can, so please
+send me ones that you create!
+
+You can follow the examples in the source code, but here is how you
+should write your closures.
+
+You need to provide both closures. Start of with the basic subroutine
+stub to do this. Create a lexical array in the scope of the subroutine.
+The two closures will share this variable. Create two closures: one
+of give to C<find()> and one to access the lexical array.
+
+ sub find_by_foo
+ {
+ my @args = @_;
+
+ my @found = ();
+
+ my $finder = sub { push @found, $File::Find::name if ... };
+ my $reporter = sub { @found };
+
+ return( $finder, $reporter );
+ }
+
+The filename should be the full path to the file that you get
+from C<$File::Find::name>, unless you are doing something wierd,
+like C<find_by_directory_contains()>.
+
+Once you have something, send it to me at C<< <bdfoy@cpan.org> >>. You
+must release your code under the Perl Artistic License.
+
+=head1 TO DO
+
+* more functions!
+
+* need input on how things like mod times work on other operating
+systems
+
+=head1 SEE ALSO
+
+L<File::Find>
+
+Randal Schwartz's C<File::Finder>, which does the same task but
+differently.
+
+=head1 SOURCE AVAILABILITY
+
+This module is in Github:
+
+ git://github.com/briandfoy/file-find-closures.git
+
+=head1 AUTHOR
+
+brian d foy, C<< <bdfoy@cpan.org> >>
+
+Some functions implemented by Nathan Wagner, C<< <nw@hydaspes.if.org> >>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (c) 2004-2014, brian d foy, All Rights Reserved.
+
+You may redistribute this under the same terms as Perl itself.
+
+=cut
+
+"Kanga and Baby Roo Come to the Forest";
@@ -1,10 +1,9 @@
-# $Id$
use strict;
use File::Find qw(find);
use File::Spec::Functions qw(curdir);
-use Test::More tests => 12;
+use Test::More 0.95;
use_ok( "File::Find::Closures" );
@@ -20,22 +19,25 @@ my @tuples = (
foreach my $tuple ( @tuples )
{
- my( $dir, $expected_count ) = @$tuple;
+ subtest $tuple->[0] => sub {
+ my( $dir, $expected_count ) = @$tuple;
- my( $finder, $reporter ) = File::Find::Closures::find_regular_files();
- isa_ok( $finder, ref sub {} );
- isa_ok( $reporter, ref sub {} );
+ my( $finder, $reporter ) = File::Find::Closures::find_regular_files();
+ isa_ok( $finder, ref sub {} );
+ isa_ok( $reporter, ref sub {} );
- find( $finder, $dir );
+ find( $finder, $dir );
- my @files = $reporter->();
- # diag( "Found dirs @dirs" );
+ my @files = $reporter->();
+ #diag( "Found files @files" );
- my $files = $reporter->();
- isa_ok( $files, ref [], "Gets anonymous array in scalar context" );
+ my $files = $reporter->();
+ isa_ok( $files, ref [], "[$tuple->[0]] Gets anonymous array in scalar context" );
- is( scalar @files, $expected_count, "Found right number of regular files" );
+ is( scalar @files, $expected_count, "[$tuple->[0]] Found right number of regular files" );
- is( scalar @$files, $expected_count, "Found right number of regular files" );
+ is( scalar @$files, $expected_count, "[$tuple->[0]] Found right number of regular files" );
+ }
}
+done_testing();