rovf has asked for the wisdom of the Perl Monks concerning the following question:

I'm looking for an elegant way of copying recursively a directory tree (similar to what File::Copy::Recursive does), but with the added twist that I want to exclude certain subdirectories (for example, .svn Subversion directories or tmp Tempdirectories).

One possibility would be to use File::Find, create directories on the fly if needed, and doing nothing if $File::Find::name contains an "unwanted" component in its path.

While this would work, I wonder whether there exists already on CPAN a module with a more convenient interface (for example, a recursive copy function which accepts a pattern of names which should excluded from the copy process). I did a CPAN search, but didn't find anything useful - but maybe I just couldn't find it.

-- 
Ronald Fischer <ynnor@mm.st>

Replies are listed 'Best First'.
Re: Recursive File Copy question
by moritz (Cardinal) on Jul 21, 2008 at 11:11 UTC

      I was not aware that rsync also runs on Windows (my application is supposed to transparently work on Windows, Linux and the usual Unix favours), but I will have a look at the links which you provided. Thanks a lot.

      -- 
      Ronald Fischer <ynnor@mm.st>
Re: Recursive File Copy question
by broomduster (Priest) on Jul 21, 2008 at 11:03 UTC
    I stumbled across File::Find::Node recently when looking for something else. I have not used this myself, but the prune method seems to do what you want.

      Thanks, I'll have a look at it.

      -- 
      Ronald Fischer <ynnor@mm.st>
Re: Recursive File Copy question
by dHarry (Abbot) on Jul 21, 2008 at 14:55 UTC

    Cookbook section 9.7. Processing All Files in a Directory Recursively;-)

    Your code can set $File::Find::prune to true to tell find not to descend into the directory just seen (unless bydepth was specified!) Check http://perldoc.perl.org/File/Find.html for details.

    There are many interesting options to tailor the behavior of find.

      Your code can set $File::Find::prune

      Thanks! I missed the part about prune when I looked at the File::Find perldoc! Didn't read careful enough.

      -- 
      Ronald Fischer <ynnor@mm.st>
Re: Recursive File Copy question
by BrowserUk (Patriarch) on Jul 21, 2008 at 15:17 UTC

    On windows, I'd use xcopy /exclude:fileOfThingsToExclude src dst.

    Eg. put \tmp\ & .svn\ on separate lines in fileOfThingsToExclude and tmp dirs off the root of any drive, and .svn\ dirs anywhere in a directory tree will be skipped.

    Mostly because it will copy acls (or not as you need), and a bunch of other useful options. But also, because it's faster than pretty much anything else.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      On windows, I'd use xcopy /exclude:fileOfThingsToExclude src dst

      Yes, but when I do this from perl, my program would not be portable to other platforms anymore.

      -- 
      Ronald Fischer <ynnor@mm.st>

        There are usually so many special cases to be dealt with when dealing with filesystems, that it doesn't make sense to try and use the same code on Win32 and *nix-like systems. So don't try:

        if( $^O eq 'mswin32' ) { ## use xcopy } elsif( $^O =~ m[(linux|unix|whatever)] ) { ## use something else } else { ## use another something else ## or throw up your hands in disgust. }

        What do I mean by special cases?

        1. *nix filesystems have:
          • a unified filespace;
          • soft & hard links;
          • chmod, chown, chgrp;
          • case-sensitivity;
          • Unicode filenames?;
          • other;
        2. Win32 filesystems have:
          • drives;
          • UNCs;
          • shares;
          • substs;
          • junctions;
          • streams;
          • attributes;
          • ACLs;
          • case-transparency;
          • long & short filenames;
          • Wide-character filenames;
          • other;
        3. Other non-disish/non-*nixish filesystems?

          ...

        Mixing all the special cases together and trying to deal with them in-line, is an exercise in frustration & complexity and is doomed to years of bugs and failures.

        Make a high-level, up-front decision as to which system you are on and then load a different module or use a different subroutine and keep the logic simple(r).


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Recursive File Copy question
by actualize (Monk) on Jul 21, 2008 at 18:02 UTC

    Another good reference is from Chapter 9 of Intermediate perl(Practical Reference Tricks). In the section "Building recursively defined data" There is an explanation on how to gather data from a directory recursively and then store it in a complex data structure.

Re: Recursive File Copy question
by JavaFan (Canon) on Jul 22, 2008 at 13:16 UTC
    Seems like 'tar' using its --exclude PATTERN option is your friend. And yes, tar has been ported to the Windows platform as well.