File-Slurp-Tree
view release on metacpan or search on metacpan
lib/File/Slurp/Tree.pm view on Meta::CPAN
File::Slurp::Tree - slurp and emit file trees as nested hashes
=head1 SYNOPSIS
# (inefficiently) duplicate a file tree from path a to b
use File::Slurp::Tree;
my $tree = slurp_tree( "path_a" );
spew_tree( "path_b" => $tree );
=head1 DESCRIPTION
File::Slurp::Tree provides functions for slurping and emitting trees
of files and directories.
# an example of use in a test suite
use Test::More tests => 1;
use File::Slurp::Tree;
is_deeply( slurp_tree( "t/some_path" ), { foo => {}, bar => "sample\n" },
"some_path contains a directory called foo, and a file bar" );
The tree datastructure is a hash of hashes. The keys of each hash are
names of directories or files. Directories have hash references as
their value, files have a scalar which holds the contents of the file.
=head1 EXPORTED ROUTINES
=head2 slurp_tree( $path, %options )
return a nested hash reference containing everything within $path
%options may include the following keys:
=over
=item rule
a L<File::Find::Rule> object that will match the files and directories
in the path. defaults to an empty rule (matches everything)
=back
=cut
sub slurp_tree {
my $in = shift;
my %args = @_;
# top must not have a trailing slash, in may. this fixes Greg's bug
# and allows in to be "/"
(my $top = $in) =~ s{/$}{};
my $rule = $args{rule} || File::Find::Rule->new;
my $tree = {};
for my $file ( $rule->in( $in ) ) {
next if $file eq $top;
(my $rel = $file) =~ s{^\Q$top\E/}{};
next unless $rel; # it's /
#print "top:$top file:$file rel:$rel\n";
my @elems = split m{/}, $rel;
# go to the top of the tree
my $node = $tree;
# and walk along the path
while (my $elem = shift @elems) {
# on the path || a dir
if (@elems || -d $file) {
$node = $node->{ $elem } ||= {};
}
else {
# a file, slurp it
$node->{ $elem } = read_file "$file", binmode => ':raw';
}
}
}
return $tree;
}
=head2 spew_tree( $path => $tree )
Creates a file tree as described by C<$tree> at C<$path>
=cut
sub spew_tree {
my ($top, $tree) = @_;
eval { mkpath( $top ) };
for my $stem (keys %$tree) {
if (ref $tree->{$stem}) { # directory
spew_tree( "$top/$stem", $tree->{ $stem } );
}
else { # file
write_file( "$top/$stem", { binmode => ':raw' }, $tree->{ $stem } )
if defined $tree->{ $stem }; # avoid an undef warning
}
}
return 1;
}
1;
__END__
=head1 BUGS
None currently known. If you find any please contact the author.
=head1 AUTHOR
Richard Clamp <richardc@unixbeard.net>
=head1 COPYRIGHT
Copyright (C) 2003, 2006 Richard Clamp. All Rights Reserved.
This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.
=head1 SEE ALSO
L<File::Slurp>, L<Test::More>
( run in 0.676 second using v1.01-cache-2.11-cpan-71847e10f99 )