Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

Comparedirs.pl

by RayRay459 (Pilgrim)
on Feb 12, 2002 at 21:54 UTC ( [id://145000]=sourcecode: print w/replies, xml ) Need Help??
Category: NT Admin
Author/Contact Info Ray Espinoza ray.espinoza@ebay.com
Description: This script will compare the same directory on two different machines for content, size and mtime.
# Ray Espinoza
# compareDirs.pl
# 2/12/02
# This script will compare two directories, with the first being the t
+emplate
# directory.
######################################################################
+#########

#!D:/perl/bin
use strict;
use File::stat;

######################################################################
+##############
# Declaring my variables.
######################################################################
+##############

my (%hashDir1, $hashDir1, %hashDir2, $hashDir2, $key, $goodDir, $path,
+ $host1, $host2, $checkDir, $currentFile, $currentFileCD, $values, $v
+alues1, $currentFile1, $currentFile2, $currentFileX, $size, $stat, );
my %hashDir1 =();
my %hashDir2 =();

######################################################################
+##############
# Asking for hostnames to process and opening directories.
######################################################################
+##############

print "What host would you like to use as template: ?\n";
chomp($host1 = <STDIN>);

print "Whats the path you want to use? \n";
chomp($path = <STDIN>);
$goodDir = "//" . $host1 . $path;
print "Template directory is : $goodDir" . "\n";
opendir(GD, $goodDir) or die "Can't open $goodDir : $!";

print "what host would you like to examine? \n";
chomp($host2 = <STDIN>);
$checkDir = "//" . $host2 . $path;
opendir(CD, $checkDir) or die "Can't open $checkDir : $!";

print "The log file results.txt will appear in the working directory.\
+n";
open(OUT, ">>results.txt");

######################################################################
+##############
# Reading the contents of the first directory, stating each file and c
+reating a hash.
# Uncomment out the print lines to print the files and or values.
######################################################################
+##############

while($currentFile = readdir(GD)) {
    
    $currentFile1 = "//" . $host1 . $path . $currentFile;
    #print $currentFile1 . "\n";
    $values = stat($currentFile1) or warn "can't stat the file :$!\n";
    #print $values->size . "\n";
    #print $values->mtime. "\n";
    $hashDir1{$currentFile} = {    size =>$values->size,
                                mtime =>$values->mtime,
                                };
    
    }
    
######################################################################
+##############
# Uncomment out if you want to print host1's files and sizes.
######################################################################
+##############

#print "$host1 's Directory has these files with these sizes:\n";
#foreach $key(keys(%hashDir1)){
    
    #print "$key,$hashDir1{$key}{'size'}\n";
    #}

######################################################################
+##############
# Reading the contents of the second directory, stating each file and 
+creating a hash.
# Uncomment out the print lines to print the files and or values.
######################################################################
+##############

while($currentFileCD = readdir(CD)) {
    $currentFile2 = "//" . $host2 . $path . $currentFileCD;
    #print $currentFile2 . "\n";
    $values1 = stat($currentFile2) or warn "can't stat the file: $!\n"
+;
    $hashDir2{$currentFileCD} = {    size =>$values1->size,
                                mtime =>$values1->mtime,
                                };
    
}

######################################################################
+##############
# Does the file exist in host2's directory. if so next statement if no
+t, enter loop.
######################################################################
+##############

foreach $key(keys(%hashDir1)){
    if(!exists ($hashDir2{$key})){
        print "$key doesn't exist on $host2.\n";
        print OUT "$key doesn't exist on $host2.\n";
        next;
        }
        
######################################################################
+##############
# Do the files sizes match?
######################################################################
+##############
    
    elsif(!$hashDir1{$key}{'size'} == $hashDir2{$key}{'size'}){
        print "$key 's sizes don't match on $host2.\n";
        print OUT "$key 's sizes don't match on $host2.\n";
        next;
        }

######################################################################
+##############
# Do the mod times match?
######################################################################
+##############
    
    elsif(!$hashDir1{$key}{'mtime'} == $hashDir2{$key}{'mtime'}){
        print "$key 's modtimes are different on $host2.\n";
        print OUT "$key 's modtimes are different on $host2.\n";
        }


}
Replies are listed 'Best First'.
Re: Comparedirs.pl
by rob_au (Abbot) on Feb 13, 2002 at 10:09 UTC
    A couple of comments on your code ...

    The readdir function iterates through each directory entry opened by opendir - Your code doesn't test whether the returned entry is either a file or directory and fails to iterate through any sub-directories present within the test directories. While not a problem per se, it does mean that great differences can exist between directories without being reported by your script.

    Another issue lies with the order of code when calling stat on the returned directory entry, specifically the following code segment:

    $values1 = stat($currentFile2) or warn "can't stat the file: $!\n"; $hashDir2{$currentFileCD} = { size =>$values1->size, mtime =>$values1->mtime, };

    While a warning is generated when the file stat fails, your code continues through and still assigns return values from the failed stat to the directory hash. An alternate (more defensive) way to write this code would be:

    if ( my $values = stat($currentFile2) ) { $hashDir2{ $currentFileCD } = { size => $values->size, mtime => $values->mtime } } else { warn "can't stat the file: $!\n" }

    If you want to build a more robust file comparison tool that incorporates directory checking, you may want to look at the source to File::Find::Duplicates which builds an intermediate array of stat values for files found through File::Find.

    On a much smaller and less significant note ... "This script will compare the same directory on two different machines for content, size and mtime" ... Where is the code comparing file content?

    :-)

     

    perl -e 's&&rob@cowsnet.com.au&&&split/[@.]/&&s&.com.&_&&&print'

      Also to add just a small comment, at the beginning of the code you redeclare the variables $hashDir1 and $hashDir2. Running under 5.6 with the -w flag, I got the errors.
      "my" variable %hashDir1 masks earlier declaration in same scope at tes +t.pl line xx. "my" variable %hashDir2 masks earlier declaration in same scope at tes +t.pl line xx.

      Rich36
      There's more than one way to screw it up...

      Thank you very much for your advice. It is very much appreciated. The reason i posted my code was to make it better and learn. I will make the change by adding the if statement, when stat'ing the file, to get rid of return values of the failed stat. The code was ment to compare directory content, not file content. if it matched in size and modtime, thats all i was looking for. do you think thats wrong. please let me know.
      thanks again
      Ray
        Please don't get me wrong at all Ray - My comments were intended to give you feedback and encourage you on the code, not discourage you at all. If the program does what you want it to do and you are happy with it, ignore everyone else and be happy that you were able to solve a problem with your knowledge of Perl.

        Good luck! :-)

         

        perl -e 's&&rob@cowsnet.com.au&&&split/[@.]/&&s&.com.&_&&&print'

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: sourcecode [id://145000]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others perusing the Monastery: (7)
As of 2024-03-28 22:06 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found