tags:

views:

139

answers:

3

I have a folder called "Lib" in my drive it contains many files inside and I have a problem that this "Lib" folder is there in many other places in the drive. My Perl script has to copy the contents from folder "Lib" which are latest updated and paste it in the folder "d:\perl\Latest_copy_of_Lib"

For example, I have a Lib folders in d:\functions, d:\abc, and many other places. I want to find the latest copy of each file in those directories. So, if the file d:\functions\foo.txt was last modified on 2009-10-12 and d:\abc\foo.txt was last modified on 2009-10-13, then I want the version in d:\abc to by copied to the target directory.

I have used file::find but it searches in whole dir and copies the contents that are not latest copy.

+2  A: 

You need to use File::Find to create a hash of files to move. Only put the path to a file in the hash if the file is newer than the path already stored in the hash. Here is a simple implementation. Note, there may be problems on the windows platform, I am not used to using File::Spec to work with files and pathes in a cross platform manner.

#!/usr/bin/perl

use warnings;
use strict;

use File::Find;
use File::Spec;

my %copy;

my @sources = qw{
    /Users/cowens/foo/Lib
    /Users/cowens/bar/Lib
    /Users/cowens/baz/Lib
};

find sub {
    my ($volume, $dir, $file) = File::Spec->splitpath($File::Find::name);
    my @dirs                  = File::Spec->splitdir($dir);
    my @base                  = ($volume); #the base directory of the file
    for my $dir (@dirs) {
        last if $dir eq 'Lib';
        push @base, $dir;
    }
    #the part that is common among the various bases
    my @rest = @dirs[$#base .. $#dirs]; 
    my $base = File::Spec->catdir(@base);
    my $rest = File::Spec->catfile(@rest, $file);

    #if we don't have this file yet, or if the file is newer than the one
    #we have
    if (not exists $copy{$rest} or (stat $File::Find::name)[9] > $copy{$rest}{mtime}) {
        $copy{$rest} = {
            mtime => (stat _)[9],
            base  => $base
        };
    }
}, @sources;

print "copy\n";
for my $rest (sort keys %copy) {
    print "\t$rest from $copy{$rest}{base}\n";
}
Chas. Owens
hi its taking the copy of all the contents from the Lib and printing it.This is not want if any updation happend in the Lib folder recently it has to take only that copy alone. say for ex if one Lib folders contains a.txt then am making a change in d:\abc\Libplacing b.txt in that path it has to search while dir and take only b.txt since i have removed a.txt and replaced with b.txt in that path alone not in all the paths.
lokesh
+8  A: 

I think you just described rsync. Unless you have some sort of weird requirements here, I don't think you need to write any code to do this. I certainly wouldn't reach for Perl to do the job you described.

brian d foy
A: 

If you can standardize on a single location for your libraries, and then use one of the following:

set PERL5LIB Environment variable and add

use lib 'C:\Lib';

or

perl -I C:\Lib myscript

Any of these will give you a single copy of your lib directory that any of your scripts will be able to access.

Sean McMillan