File::Find and tree copying

Do you have a question? Post it now! No Registration Necessary.  Now with pictures!

Threaded View

As usually, my apologies for the newbie type question from an infrequent

I have a directory tree (path is $tree0), and I would like to duplicate the
tree structure into two other tree roots ($tree1 and $tree2). I want to
process the files in the original tree with two different subroutines, call
them Process1 and Process2 so that the files in the duplicated trees are not
really exact copies but versions produces by Process1(individualFile) and

I can find my way down the original tree OK using File::Find, get the name
($File::Find::name) (.... this is progress for a novice, so don't laugh) and
do something with the file. But duplicating the structure has me completely

use File::Find;
my $tree0="c:\k\origtree";

# Find the original files
  find(\&processAllFiles, $tree0);

# Subroutine that decends the tree.
sub processAllFiles{
    print "$File::Find::name\n";


I would appreciate any help, whether general pointer to a place to read, an
appropriate old note in the archive, or code snippet.


Mark R. Diamond

Re: File::Find and tree copying

Quoted text here. Click to load it

Calling the operations Process1 and Process2 adds nothing to help us
understand your problem.  What do Process1 and Process2 expect as an
argument (individualFile)?  An open filehandle?  A file name? File content
as a single multiline string?  A list of strings?  And how do they deliver
the modified file?  As a string?  A list of lines?  Does it write it to
disk somewhere?  Without that information, "Process1(individualFile)" is
nothing but claptrap (and not even Perl claptrap at that).

I'll assume that Process1() has two arguments, one the name of the
original file and the other the name of the new file to write, so a
call would look like

    Process1( $original, $new);

Quoted text here. Click to load it

No strict, no warnings!

Quoted text here. Click to load it

I'll pretend you have only one target tree $root1 and only one file-
modifying process.

You'll have to do different things depending on whether the file in
$File::Find::name is a directory or a normal file.  If it is a directory,
crate the "parallel" directory in $tree1.  If it is a file, the target
directory will already have been created, just call Process1 with the
original and new names.

For both actions you'll want to change (the initial) part of a path
name to something else.  This applies to directories as well as files,
so it's a candidate for a subroutine.  Untested:

    use strict; use warnings;
    use File::Find;
    use Errno qw( EEXIST);  # perldoc Errno for more

    my $tree0 = '...'; # substitute your...
    my $tree1 = '...'; # ...actual locations

    find sub {
        if ( -d ) {
            my $dir = change_path( $File::Find::Name, $tree0, $tree1);
            mkdir $dir or $!{ EEXIST} or die "Can't create directory $dir: $!";
        } else {
            my $out = change_path( $File::Find::Name, $tree0, $tree1);
            Process1( $File::Find::name, $out);
    }, $tree0;

    sub change_path {
        my ( $path, $old_prefix, $new_prefix) = @_;
        die "'$path' doesn't begin with '$old_prefix'" if
            index( $path, $old_path) != 0;
        substr( $path, 0, length $old_prefix) = $new_prefix;


Site Timeline