Monday, March 17, 2008

Perl Directory Permissions Difference Script For Directories

Howdy,

Today's Perl script is a slight variation on the "diff -r" command (actually the diff command with -r option) for both Linux and Unix. "diff -r" recursively checks directories to report on the differences, much in the same way diff (without arguments) might compare two files. This is a great command if you need to manage separate directory trunks or the find the difference in them. For an example, consider two directories we've created, each with a few files in it, and the output that "diff -r" produces:

host # diff -r scripts1 scripts2
host #


No output means both directories are identical.

There do exist situations, however, for which "diff -r" falls a bit short. The pdiff Perl script presented today works more like "diff -rs" (the -s option let's you view two files, or directories, side by side). Using our previous example, we'd get this output instead:

host # diff -rs scripts1 scripts2
Files scripts1/script1 and scripts2/script1 are identical
Files scripts1/script1.bak and scripts2/script1.bak are identical
Files scripts1/script2 and scripts2/script2 are identical
Files scripts1/script2.bak and scripts2/script2.bak are identical
Files scripts1/script3 and scripts2/script3 are identical
Files scripts1/script3.bak and scripts2/script3.bak are identical


A little bit better, since it will at least tell you that the directories are identical ;)

However, diff doesn't take directory permissions, or user/group ownership, into consideration, which is why I wrote this script. If we run pdiff against those same 2 directories, we get this output:

./pdiff scripts1 scripts2
0644 script1---eggi newpeople 0755 script1---eggi newpeople
0644 script1.bak---eggi newpeople 0755 script1.bak---eggi newpeople
0644 script2---eggi newpeople 0755 script2---eggi newpeople
0644 script2.bak---eggi newpeople 0755 script2.bak---eggi newpeople
0644 script3---eggi newpeople 0755 script3---eggi newpeople
0644 script3.bak---eggi newpeople 0755 script3.bak---eggi newpeople


Notice the difference? ;)

Hope you find good use for this script, and enjoy!

Cheers,


Creative Commons License


This work is licensed under a
Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License

#!/usr/bin/perl

#
# pdiff - diff directories with
# user/group and permissions checked
#
# 2008 - Mike Golvach - eggi@comcast.net
#
# Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License
#

if ($#ARGV != 1) {
print "Usage: $0 dir1 dir2\n";
exit;
}

$firstdir=$ARGV[0];
$seconddir=$ARGV[1];

@firstfiles=`ls -l $firstdir|grep -v total`;
@secondfiles=`ls -l $seconddir|grep -v total`;
@file1 = ();
@file2 = ();

foreach $firstbit (@firstfiles) {
@firstparts = split(/ * */, $firstbit);
@perms = split(//, $firstparts[0]);
chomp(@perms);
@user = ($perms[1], $perms[2], $perms[3]);
@group = ($perms[4], $perms[5], $perms[6]);
@other = ($perms[7], $perms[8], $perms[9]);
$ucounter = 0;
$gcounter = 0;
$ocounter = 0;
$majordiff = 0;
foreach $perm (@user) {
if ($perm eq "r") {
$ucounter += 4;
} elsif ($perm eq "w") {
$ucounter += 2;
} elsif ($perm eq "x") {
$ucounter += 1;
} elsif ($perm eq "s") {
$ucounter += 1;
$majordiff += 4;
}
}
foreach $perm (@group) {
if ($perm eq "r") {
$gcounter += 4;
} elsif ($perm eq "w") {
$gcounter += 2;
} elsif ($perm eq "x") {
$gcounter += 1;
} elsif ($perm eq "s") {
$gcounter += 1;
$majordiff += 2;
}
}
foreach $perm (@other) {
if ($perm eq "r") {
$ocounter += 4;
} elsif ($perm eq "w") {
$ocounter += 2;
} elsif ($perm eq "x") {
$ocounter += 1;
} elsif ($perm eq "t") {
$ocounter += 1;
$majordiff += 1;
}
}
@permissions = ($majordiff, $ucounter, $gcounter, $ocounter);
$permissions = join("", @permissions);
# print "$permissions $firstparts[8]";
chomp($firstparts[8]);
push(@file1, "$permissions $firstparts[8]---$firstparts[2] $firstparts[3]");
}
foreach $firstbit (@secondfiles) {
@firstparts = split(/ * */, $firstbit);
@perms = split(//, $firstparts[0]);
chomp(@perms);
@user = ($perms[1], $perms[2], $perms[3]);
@group = ($perms[4], $perms[5], $perms[6]);
@other = ($perms[7], $perms[8], $perms[9]);
$ucounter = 0;
$gcounter = 0;
$ocounter = 0;
$majordiff = 0;
foreach $perm (@user) {
if ($perm eq "r") {
$ucounter += 4;
} elsif ($perm eq "w") {
$ucounter += 2;
} elsif ($perm eq "x") {
$ucounter += 1;
} elsif ($perm eq "s") {
$ucounter += 1;
$majordiff += 4;
}
}
foreach $perm (@group) {
if ($perm eq "r") {
$gcounter += 4;
} elsif ($perm eq "w") {
$gcounter += 2;
} elsif ($perm eq "x") {
$gcounter += 1;
} elsif ($perm eq "s") {
$gcounter += 1;
$majordiff += 2;
}
}
foreach $perm (@other) {
if ($perm eq "r") {
$ocounter += 4;
} elsif ($perm eq "w") {
$ocounter += 2;
} elsif ($perm eq "x") {
$ocounter += 1;
} elsif ($perm eq "t") {
$ocounter += 1;
$majordiff += 1;
}
}
@permissions = ($majordiff, $ucounter, $gcounter, $ocounter);
$permissions = join("", @permissions);
# print "$permissions $firstparts[8]";
chomp($firstparts[8]);
push(@file2, "$permissions $firstparts[8]---$firstparts[2] $firstparts[3]");
}

$file1count = @file1;
$file2count = @file2;

if ( $file1count > $file2count ) {
$filecount = $file1count;
} else {
$filecount = $file2count;
}

$indexer = 0;
while ( $indexer < $filecount ) {
chomp($file1[$indexer]);
chomp($file2[$indexer]);
printf("%-40s%s\n", $file1[$indexer],$file2[$indexer]);
$indexer++;
}


, Mike