#!/usr/bin/perl ########################### ### Autor: Sebastian Enger / B.Sc. ### Copyright: Sebastian Enger ### Licence: BSD ### Version: 1.1.b - 20080716@19.Uhr ### Contact: sebastian.enger@gmail.com | icq: 135846444 ### Web: http://www.bitjoe.de - Handy P2P Suchmaschine und Downloads ### Latest Version: PENDRIVE:\Programming\Perl\IncrementalBackup ########################### use strict; use File::Find; # perl -MCPAN -e 'force install "File::Find"' use File::Copy; # perl -MCPAN -e 'force install "File::Copy"' use File::Path; # perl -MCPAN -e 'force install "File::Path"' # debug # use Data::Dumper; print "$0 initializing\n"; my $SourceFolder = $ARGV[0] || 'F:\My Business'; # F: - source folder my $DestFolder = $ARGV[1] || 'I:\My Business'; # I: - destination folder | 'N:\USBSTICK\My Business' my (@tmp) = split(":", $DestFolder ); my $Destination = $tmp[0] . ":"; # I: - destination to which is copied #my $DestFileStructure = {}; # keeps filestructure of DestFolder my $ErrorFileStructure = {}; # keeps files that failed copying my $CopyErrorMessage = ""; # keeps error message for final output of files that have not been copied successfully my $SourceFileCount = 0; # keeps count of overall files in source folder my $CopiedFileCount = 0; # keeps count of file that must be copied because source files are newer than dest files my $FailedCopyFile = "failed_copy_files.txt"; # textfile with failed copied files my $StartExecTime = time(); my $EndExecTime = 0; use constant DEBUG => 1; # 2 or 1 or 0 unless ( defined($SourceFolder) && defined($DestFolder) ) { print "Usage: perl $0 SourceFolder Destination \n"; print "Usage: Or do define \$SourceFolder and \$DestFolder on top of File $0!\n"; exit(0); }; # unless ( # prepare DestinationFolder Structure # find(\&DestStructure, $DestFolder); # keeps count of overall files in dest folder -before any copying- # my $DestFileCount = keys(%{$DestFileStructure}); # prepare files from SourceFolder find(\&SourceStructure, $SourceFolder); my $FailedFileCount = keys(%{$ErrorFileStructure}); $EndExecTime = time(); if ( $FailedFileCount > 0 ) { open(LOG,">$FailedCopyFile"); LOG->autoflush(1); while( my ($file,$type) = each(%{$ErrorFileStructure}) ){ print LOG "[$type] Failed to copy Source File $FailedCopyFile\n"; }; # while( my ($file,$type) = each(%{$ErrorFileStructure}) ){ close LOG; $CopyErrorMessage = "Failed to copy $FailedFileCount - dumped failed copy list to $FailedCopyFile"; }; # if ( $FailedFileCount > 0 ) { if ( DEBUG >= 1 ) { print "Copy assignment from source $SourceFolder to destination $DestFolder\n"; print "Started @ ".MySQLDateTime($StartExecTime)." o'clock\n"; print "Ended @ ".MySQLDateTime($EndExecTime)." o'clock\n"; print "Working Time @ ".sprintf("%.0f", ( ( $EndExecTime - $StartExecTime ) / 60 ) )." minutes\n"; print "Copied Files @ $CopiedFileCount Files/Dirs from approximatly $SourceFileCount Files\n"; print "$CopyErrorMessage\n\a"; # incl alarm sleep 200; exit(0); }; # if ( DEBUG >= 1 ) { sub SourceStructure(){ # $_ is set to the current file name # $File::Find::dir is set to the current directory # $File::Find::name is set to "$File::Find::dir/$_" # you are chdir()'d to $File::Find::dir my $SourceFilename = $File::Find::name; # my $SourceFirname = $File::Find::dir; next if ( $SourceFilename eq $SourceFolder ); # ignore $SourceFolder $SourceFileCount++; my (undef,$tmpfilename) = split(':', $SourceFilename); my $DestFilename = $Destination.$tmpfilename; if ( -e $DestFilename ) { print "DEBUG: $DestFilename alread exists on device\n" if ( DEBUG > 1 ); if ( -f $SourceFilename ) { # is_file my $LastModifyTimeSource = (stat($SourceFilename))[9]; my $LastModifyTimeDest = (stat($DestFilename))[9]; my $TimeDiff = $LastModifyTimeSource - $LastModifyTimeDest; my $TimeDiffMin = sprintf("%.0f", $TimeDiff / 60 ); my $TimeDiffHour = sprintf("%.0f", $TimeDiff / ( 60 * 60 )); my $TimeDiffDays = sprintf("%.0f", $TimeDiff / ( 60 * 60 * 24) ); # $FileSizeSource = (stat($SourceFilename))[7]; if ( $LastModifyTimeSource > $LastModifyTimeDest ) { $CopiedFileCount++; # print "[$CopiedFileCount/$DestFileCount] - Modified at ".MySQLDateTime($LastModifyTimeSource)." for File '$SourceFilename' \n"; # print "[$CopiedFileCount/$DestFileCount] - Modified before $TimeDiffMin min |$TimeDiffHour h| $TimeDiffDays d for File '$SourceFilename' \n"; print "[$CopiedFileCount] - Modified before $TimeDiffHour hours | $TimeDiffMin minutes for File '$SourceFilename' \n" if ( DEBUG == 1 ); eval { copy($SourceFilename, $DestFilename) }; if ($@) { $ErrorFileStructure->{$DestFilename} = 'FILE'; print "Couldn't copy $SourceFilename TO $DestFilename: $@\n" if ( DEBUG > 1 ); }; # if ($@) { }; # if ( $LastModifyTimeSource > $LastModifyTimeDest ) { }; # if ( -f $SourceFilename ) { # is_file ### is_dir -> it exists we dont need to do something } else { print "DEBUG: $DestFilename must be created on device\n" if ( DEBUG > 1 ); if ( -f $SourceFilename ) { # is_file print "[$CopiedFileCount] - First Time Copy for '$SourceFilename' \n" if ( DEBUG == 1 ); eval { copy($SourceFilename, $DestFilename) }; if ($@) { $ErrorFileStructure->{$DestFilename} = 'FILE'; print "Couldn't copy $SourceFilename TO $DestFilename: $@\n" if ( DEBUG > 1 ); }; # if ($@) { $CopiedFileCount++; } elsif ( -d $SourceFilename ) { # is_dir print "[$CopiedFileCount] - First Time Dir-Create for '$SourceFilename' \n" if ( DEBUG == 1 ); eval { mkpath($DestFilename) }; # File::Path if ($@) { $ErrorFileStructure->{$DestFilename} = 'DIR'; print "Couldn't create $DestFilename: $@\n" if ( DEBUG > 1 ); }; # if ($@) { $CopiedFileCount++; }; # if ( -f $SourceFilename ) { }; # if ( exists($DestFileStructure->{$DestFilename}) ) { }; # sub SourceStructure(){ #sub DestStructure(){ # # my $DestFilename = $File::Find::name; # $DestFileStructure->{$DestFilename} = 0; # #}; # sub DestStructure(){ sub MySQLDateTime(){ my $timestamp = shift; my ( $sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst ) = localtime($timestamp); $year += 1900; $mon += 1; if ( length($mon) == 1 ) { $mon = "0". $mon; }; if ( length($mday) == 1 ) { $mday = "0". $mday; }; if ( length($sec) == 1 ) { $sec = "0". $sec; }; if ( length($min) == 1 ) { $min = "0". $min; }; if ( length($hour) == 1 ) { $hour = "0". $hour; }; return $year ."-". $mon ."-". $mday .' '. $hour .':'. $min .':'. $sec; }; # sub MySQLDateTime() {}