Initial commit.
This commit is contained in:
349
DirWalk.pm
Normal file
349
DirWalk.pm
Normal file
@@ -0,0 +1,349 @@
|
||||
# Copyright (c) 2005-2006 Jens Luedicke <jensl@cpan.org>. All rights reserved.
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the same terms as Perl itself.
|
||||
|
||||
package File::DirWalk;
|
||||
use base qw(Exporter);
|
||||
|
||||
our $VERSION = '0.4';
|
||||
our @EXPORT = qw(FAILED SUCCESS ABORTED PRUNE);
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
|
||||
use File::Basename;
|
||||
use File::Spec;
|
||||
|
||||
use constant SUCCESS => 1;
|
||||
use constant FAILED => 0;
|
||||
use constant ABORTED => -1;
|
||||
use constant PRUNE => -10;
|
||||
|
||||
sub new {
|
||||
my ($class) = @_;
|
||||
my $self = bless {}, $class;
|
||||
|
||||
$self->{onBeginWalk} = sub { SUCCESS };
|
||||
$self->{onLink} = sub { SUCCESS };
|
||||
$self->{onFile} = sub { SUCCESS };
|
||||
$self->{onDirEnter} = sub { SUCCESS };
|
||||
$self->{onDirLeave} = sub { SUCCESS };
|
||||
|
||||
$self->{depth} = 0;
|
||||
$self->{depth_count} = 0;
|
||||
|
||||
$self->{filesInDir} = 0;
|
||||
|
||||
# $self->{customResponse} = {};
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub onBeginWalk {
|
||||
my ($self,$func) = @_;
|
||||
$self->{onBeginWalk} = $func;
|
||||
}
|
||||
|
||||
sub onLink {
|
||||
my ($self,$func) = @_;
|
||||
$self->{onLink} = $func;
|
||||
}
|
||||
|
||||
sub onFile {
|
||||
my ($self,$func) = @_;
|
||||
$self->{onFile} = $func;
|
||||
}
|
||||
|
||||
sub onDirEnter {
|
||||
my ($self,$func) = @_;
|
||||
$self->{onDirEnter} = $func;
|
||||
}
|
||||
|
||||
sub onDirLeave {
|
||||
my ($self,$func) = @_;
|
||||
$self->{onDirLeave} = $func;
|
||||
}
|
||||
|
||||
sub setDepth {
|
||||
my ($self,$v) = @_;
|
||||
$self->{depth} = $v;
|
||||
}
|
||||
|
||||
sub getDepth {
|
||||
my ($self) = @_;
|
||||
return $self->{depth_count};
|
||||
}
|
||||
|
||||
sub currentDir {
|
||||
my ($self) = @_;
|
||||
return $self->{currentDir};
|
||||
}
|
||||
|
||||
sub currentPath {
|
||||
my ($self) = @_;
|
||||
return $self->{currentPath};
|
||||
}
|
||||
|
||||
sub currentBasename {
|
||||
my ($self) = @_;
|
||||
return $self->{currentBasename};
|
||||
}
|
||||
|
||||
sub filesInDir {
|
||||
my ($self) = @_;
|
||||
return $self->{filesInDir};
|
||||
}
|
||||
|
||||
sub walk {
|
||||
my ($self,$path) = @_;
|
||||
|
||||
$self->{currentDir} = dirname($path);
|
||||
$self->{currentBasename} = basename($path);
|
||||
$self->{currentPath} = $path;
|
||||
|
||||
if ((my $r = $self->{onBeginWalk}->($path)) != SUCCESS) {
|
||||
return $r;
|
||||
}
|
||||
|
||||
if (-l $path) {
|
||||
|
||||
if ((my $r = $self->{onLink}->($path)) != SUCCESS) {
|
||||
return $r;
|
||||
}
|
||||
|
||||
} elsif (-d $path) {
|
||||
|
||||
if ($self->{depth} != 0) {
|
||||
if ($self->{depth_count} == $self->{depth}) {
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
opendir my $dirh, $path || return FAILED;
|
||||
my @dir_contents = readdir $dirh;
|
||||
@dir_contents = File::Spec->no_upwards(@dir_contents);
|
||||
|
||||
$self->{filesInDir} = scalar @dir_contents;
|
||||
|
||||
if ((my $r = $self->{onDirEnter}->($path)) != SUCCESS) {
|
||||
return $r;
|
||||
}
|
||||
++$self->{depth_count};
|
||||
|
||||
# be portable.
|
||||
my @dirs = File::Spec->splitdir($path);
|
||||
|
||||
foreach my $f (@dir_contents) {
|
||||
# be portable.
|
||||
my $path = File::Spec->catfile(@dirs, $f);
|
||||
|
||||
my $r = $self->walk($path);
|
||||
|
||||
if ($r == PRUNE) {
|
||||
next;
|
||||
} elsif ($r != SUCCESS) {
|
||||
return $r;
|
||||
}
|
||||
}
|
||||
|
||||
closedir $dirh;
|
||||
|
||||
if ((my $r = $self->{onDirLeave}->($path)) != SUCCESS) {
|
||||
return $r;
|
||||
}
|
||||
--$self->{depth_count};
|
||||
} else {
|
||||
if ((my $r = $self->{onFile}->($path)) != SUCCESS) {
|
||||
return $r;
|
||||
}
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
File::DirWalk - walk through a directory tree and run callbacks
|
||||
on files, symlinks and directories.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use File::DirWalk;
|
||||
|
||||
my $dw = File::DirWalk->new;
|
||||
|
||||
Walk through your homedir and print out all filenames:
|
||||
|
||||
$dw->onFile(sub {
|
||||
my ($file) = @_;
|
||||
print "$file\n";
|
||||
|
||||
return SUCCESS;
|
||||
});
|
||||
|
||||
$dw->walk($ENV{'HOME'});
|
||||
|
||||
Walk through your homedir and print out all directories:
|
||||
|
||||
$dw->onDirEnter(sub {
|
||||
my ($path) = @_;
|
||||
print "$path\n";
|
||||
|
||||
return SUCCESS;
|
||||
});
|
||||
|
||||
$dw->walk($ENV{'HOME'});
|
||||
|
||||
Walk through your homedir and print out all directories
|
||||
with depth 3:
|
||||
|
||||
$dw->onDirEnter(sub {
|
||||
my ($path) = @_;
|
||||
print "$path\n";
|
||||
|
||||
return SUCCESS;
|
||||
});
|
||||
|
||||
$dw->setDepth(3);
|
||||
$dw->walk($ENV{'HOME'});
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This module can be used to walk through a directory tree and run own functions
|
||||
on files, directories and symlinks.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=over 4
|
||||
|
||||
=item new()
|
||||
|
||||
Create a new File::DirWalk object.
|
||||
The constructor takes no arguments.
|
||||
|
||||
=item onBeginWalk(\&func)
|
||||
|
||||
Specify a function to be be run on beginning of a walk.
|
||||
|
||||
=item onLink(\&func)
|
||||
|
||||
Specify a function to be run on symlinks.
|
||||
|
||||
=item onFile(\&func)
|
||||
|
||||
Specify a function to be run on regular files.
|
||||
|
||||
=item onDirEnter(\&func)
|
||||
|
||||
Specify a function to be run before entering a directory.
|
||||
|
||||
=item onDirLeave(\&func)
|
||||
|
||||
Specify a function to be run when leaving a directory.
|
||||
|
||||
=item setDepth($int)
|
||||
|
||||
Set the directory traversal depth.
|
||||
Default: 0
|
||||
|
||||
=item getDepth
|
||||
|
||||
Get the directory traversal depth;
|
||||
|
||||
=item currentDir
|
||||
|
||||
The directory we are in:
|
||||
|
||||
$dw->onBeginWalk(sub {
|
||||
my ($path) = @_;
|
||||
|
||||
print "directory: " . $dir, "\n";
|
||||
print "directory: " . $dw->currentDir, "\n"; # same!
|
||||
|
||||
return SUCCESS;
|
||||
});
|
||||
|
||||
=item currentPath
|
||||
|
||||
The current path:
|
||||
|
||||
$dw->onBeginWalk(sub {
|
||||
my ($path) = @_;
|
||||
|
||||
print "directory: " . $path, "\n";
|
||||
print "directory: " . $dw->currentPath, "\n"; # same!
|
||||
|
||||
return SUCCESS;
|
||||
});
|
||||
|
||||
=item currentBasename
|
||||
|
||||
=item filesInDir
|
||||
|
||||
Returns the number of files in directory.
|
||||
Excludes . and ..
|
||||
|
||||
=item walk($path)
|
||||
|
||||
Begin the walk through the given directory tree. This method returns if the walk
|
||||
is finished or if one of the callbacks doesn't return SUCCESS.
|
||||
|
||||
=back
|
||||
|
||||
=head1 CALLBACKS
|
||||
|
||||
All callback-methods expect a function reference as their argument.
|
||||
The current path is passed to the callback function.
|
||||
|
||||
The callback function must return SUCCESS, otherwise the recursive walk is aborted and
|
||||
C<walk> returns. You don't need to define a callback if you don't need to.
|
||||
|
||||
=head1 CONSTANTS
|
||||
|
||||
File::DirWalk exports the following predefined constants
|
||||
as return values:
|
||||
|
||||
=over 4
|
||||
|
||||
=item SUCCESS (1)
|
||||
|
||||
=item FAILED (0)
|
||||
|
||||
=item ABORTED (-1)
|
||||
|
||||
=item PRUNE (-10)
|
||||
|
||||
=back
|
||||
|
||||
=head1 BUGS
|
||||
|
||||
Please mail the author if you encounter any bugs.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Jens Luedicke E<lt>jensl@cpan.orgE<gt> web: L<http://perldude.de/>
|
||||
|
||||
=head1 CHANGES
|
||||
|
||||
Version 0.4: add more methods, better testing, more documentation.
|
||||
|
||||
Version 0.3: add PRUNE constant. add option to specify the directory depth.
|
||||
|
||||
Version 0.2: platform portability fixes and more documentation
|
||||
|
||||
Version 0.1: first CPAN release
|
||||
|
||||
=head1 HISTORY
|
||||
|
||||
I wrote DirWalk.pm module for use within my 'Filer' file manager as a directory
|
||||
traversing backend and I thought it might be useful for others. It is my first
|
||||
CPAN module.
|
||||
|
||||
=head1 COPYRIGHT AND LICENCE
|
||||
|
||||
Copyright (c) 2005-2006 Jens Luedicke. All rights reserved. This program is free
|
||||
software; you can redistribute it and/or modify it under the same terms as Perl
|
||||
itself.
|
||||
|
||||
7
MANIFEST
Normal file
7
MANIFEST
Normal file
@@ -0,0 +1,7 @@
|
||||
DirWalk.pm
|
||||
MANIFEST
|
||||
META.yml
|
||||
Makefile.PL
|
||||
README
|
||||
configure
|
||||
t/1.t
|
||||
14
Makefile.PL
Normal file
14
Makefile.PL
Normal file
@@ -0,0 +1,14 @@
|
||||
use ExtUtils::MakeMaker;
|
||||
|
||||
WriteMakefile(
|
||||
'NAME' => 'File::DirWalk',
|
||||
'VERSION_FROM' => 'DirWalk.pm',
|
||||
'PREREQ_PM' => {
|
||||
'File::Basename' => 0,
|
||||
'File::Spec' => 0,
|
||||
},
|
||||
($] >= 5.005
|
||||
? (AUTHOR => 'Jens Luedicke <jensl@cpan.org>')
|
||||
: ()
|
||||
),
|
||||
);
|
||||
31
README
Normal file
31
README
Normal file
@@ -0,0 +1,31 @@
|
||||
File-DirWalk version 0.2
|
||||
=========================
|
||||
|
||||
File::DirWalk is a Perl module to walk through a directory tree
|
||||
and run own functions on directories, files and symlinks.
|
||||
|
||||
|
||||
INSTALLATION
|
||||
|
||||
To install this module type the following:
|
||||
|
||||
perl Makefile.PL
|
||||
make
|
||||
make test
|
||||
make install
|
||||
|
||||
DEPENDENCIES
|
||||
|
||||
This module requires these other modules which can be obtained from
|
||||
the CPAN <http://cpan.org> if they are not allready installed on
|
||||
your system :
|
||||
|
||||
File::Basename
|
||||
File::Spec
|
||||
|
||||
COPYRIGHT AND LICENCE
|
||||
|
||||
Copyright (c) 2005 Jens Luedicke <jensl@cpan.org>. All rights reserved.
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the same terms as Perl itself.
|
||||
|
||||
2
configure
vendored
Executable file
2
configure
vendored
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
exec perl ./Makefile.PL "$@"
|
||||
87
t/1.t
Normal file
87
t/1.t
Normal file
@@ -0,0 +1,87 @@
|
||||
use Test::Simple tests => 6;
|
||||
|
||||
use File::Basename;
|
||||
use File::DirWalk;
|
||||
|
||||
my $perl_path = dirname($^X);
|
||||
my $perl_interpreter = basename($^X);
|
||||
|
||||
ok( ref(File::DirWalk->new) eq 'File::DirWalk' ); # 1
|
||||
|
||||
$dw = new File::DirWalk;
|
||||
|
||||
$dw->onDirEnter(sub {
|
||||
my ($path) = @_;
|
||||
|
||||
if ($path eq $perl_path) {
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
});
|
||||
|
||||
ok( $dw->walk($perl_path) == FAILED ); # 2
|
||||
|
||||
$dw->onBeginWalk(sub {
|
||||
my ($path) = @_;
|
||||
if (dirname($path) eq $dw->currentDir) {
|
||||
return ABORTED;
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
});
|
||||
|
||||
ok( $dw->walk($perl_path) == ABORTED ); # 3
|
||||
|
||||
$dw->onBeginWalk(sub {
|
||||
my ($path) = @_;
|
||||
if ($path eq $dw->currentPath) {
|
||||
return ABORTED;
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
});
|
||||
|
||||
ok( $dw->walk($perl_path) == ABORTED ); # 4
|
||||
|
||||
$dw->onFile(sub {
|
||||
my ($path) = @_;
|
||||
|
||||
if (basename($path) eq $perl_interpreter) {
|
||||
return ABORTED;
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
});
|
||||
|
||||
ok( $dw->walk($perl_path) == ABORTED ); # 5
|
||||
|
||||
$dw->onFile(sub {
|
||||
my ($path) = @_;
|
||||
|
||||
if (basename($path) eq "1.t") {
|
||||
return ABORTED;
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
});
|
||||
|
||||
ok( $dw->walk($0) == ABORTED ); # 6
|
||||
|
||||
# $dw->setCustomResponse('FOOBAR', -20);
|
||||
# ok( $dw->getCustomResponse('FOOBAR') == -20); # 7
|
||||
#
|
||||
# $dw->onBeginWalk(sub {
|
||||
# my ($path) = @_;
|
||||
#
|
||||
# if ($path eq $ENV{'HOME'}) {
|
||||
# return $dw->getCustomResponse('FOOBAR');
|
||||
# }
|
||||
#
|
||||
# return FAILED;
|
||||
# });
|
||||
#
|
||||
# ok( $dw->walk($ENV{'HOME'}) == $dw->getCustomResponse('FOOBAR') ); # 8
|
||||
#
|
||||
# $dw->setCustomResponse('WOMBAT', -42);
|
||||
# ok( $dw->getCustomResponse('FOOBAR') != $dw->getCustomResponse('WOMBAT') ); # 9
|
||||
Reference in New Issue
Block a user