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

Hi please be gentle, I am very new at PERL. I am working on a script that will copy files and subdirectory within a directory into another directory on same server. I know it's weird and perhaps even dumb... but it's something I've been trying to figure out for my little site. Below are my messy code, it works, but it does not copy and replace the subdirectory files... Thanks ahead! - Meg
#!/usr/local/bin/perl #simple file replacement in perl #looks for pages that are less than 2 min old and replaces # use strict; use File::Copy; use File::Find; my $age; my $destination="/usr/local/netscape/server4/nes/publishdocs/press2/"; my $sourcedir="/usr/local/netscape/server4/nes/publishdocs/press/"; my @files=`cd $sourcedir && ls`; my @dirlist=readdir(DIR); # iterate and copy each one sub cpnewest { copy("$sourcedir$_","$destination$_"); } foreach (@files, @dirlist){ chomp; # get the age in seconds $age = (time() - (stat($sourcedir.$_))[9]); # if we files needs to be printed in unix print "\n$sourcedir.$_ is is $age seconds old\n"; if($age<120){ find(\&cpnewest, @dirlist); } }
  • Comment on Copying all files and subdirectories from one directory to another..
  • Download Code

Replies are listed 'Best First'.
Re: Copying all files and subdirectories from one directory to another..
by graff (Chancellor) on Jun 11, 2003 at 06:27 UTC
    I want to encourage you -- this is a nice exercise for learning a lot about how to use Perl effectively -- but I have to confess that for this particular problem (if I understand it right), Perl may not be the most effective tool.

    I think you want the "tar" utility, especially if you're working on a unix system (GNU tar has been ported to windows, and so has the GNU bash shell, which would also be necessary here, but the usage suggested below may have some problems on a windows system, especially if the source directory tree contains a large quantity of data, e.g. 100's of MB or more, depending on your system's disk capacity).

    The usage you'd want goes like this:

    cd destination_parent (cd source_parent; tar cf - source) | tar xf -
    That is, you set your current working directory to be the place where you want to put a copy of the source data. Then run a two-command sequence in a "group": cd to the path containing the source directory, and run tar to create a tar file containing the source tree; the "name" of the "tar file" is "-" (dash), which tar interprets as stdout. The output of this command sequence is then piped to another tar command, this one running in the destination path, and extractin data from the tar file that is given to it; in this case, the "tar file name" (dash) represents stdin.

    This will tend to run a lot faster (and is a lot easier and more robust) than any Perl script could possibly be. There are also tons of options for controlling tar's behavior: which files or subdirectories to include or exclude, based on names, dates, types, owners, etc. (The manual page for tar is rather large.)

      Note you can use -C at least with GNU tar to define the extraction destination.
      (cd source_parent; tar cf - source) | tar xf - -C destination_parent

      Makeshifts last the longest.

Re: Copying all files and subdirectories from one directory to another..
by zentara (Cardinal) on Jun 11, 2003 at 15:05 UTC
    Practice on some temp dirs first.:-)
    #!/usr/bin/perl use File::NCopy; $file = File::NCopy->new(recursive => 1); $file->copy($dir1, $dir2); # Copy $dir1 to $dir2 recursively
Re: Copying all files and subdirectories from one directory to another..
by ctilmes (Vicar) on Jun 11, 2003 at 00:21 UTC
Re: Copying all files and subdirectories from one directory to another..
by bluto (Curate) on Jun 11, 2003 at 14:53 UTC
    If your goal is to do this reliably, don't reinvent the wheel -- use rsync. It will quickly mirror directories for you. Sometimes this is already installed (e.g. some Linux boxes). Try "man rsync". If not, it's generally worth installing. See http://rsync.samba.org

    If you don't want to use rsync, see if your 'cp' has a recursive option ('-r' or '-R'). GNU cp also has a '-u' flag that only updates files that have changed. You can use the '-p' flag to preserve file timestamps.

    I'd suggest you avoid the tar solution. If something fails (like a 'cd') it can create a mess and it's not easy to detect errors with a shell pipeline.

    If this is more of a learning experience and you want to try this in perl, you'll can learn from countless others who have tried doing this by using Super Search.

    bluto

Re: Copying all files and subdirectories from one directory to another..
by TomDLux (Vicar) on Jun 11, 2003 at 18:34 UTC

    You might want to type man cp at the command line.

    cp -r /source/dir /dest/dir

    --
    TTTATCGGTCGTTATATAGATGTTTGCA

      And then do it again and notice that -r is deprecated due to unspecified behaviour in favour of -R. :)

      Makeshifts last the longest.

Re: Copying all files and subdirectories from one directory to another..
by Anonymous Monk on Jun 11, 2003 at 03:55 UTC
    That's not PERL, it looks more like Perl ... furthermore, asking people to be gentle is *muffle* ... if you suspect you're doing something dumb, you probably are ... now on to the code

    Don't do that!

    Was that too loud? Anyway, my @files=`cd $sourcedir && ls`; is yucky, as is
    sub cpnewest { copy("$sourcedir$_","$destination$_"); }
    Do you know how/why cpnewest works? Do you know why it's a bad idea?

    And last but not least, where on earth do you opendir DIR?

    You could also use a little more whitespace (indent yer code -- perltidy).

    What's the purpose of having @files, @dirlist? Does it really matter that you process/check @files first?

    I hope this is enough food for thought (if you're wondering what kind of food, angel-food ).