Comparer rapidement les classes contenues dans deux jar. Le but n’est pas de connaitre l’exacte difference, mais de savoir quel fichier .class est different entre deux jar. D’autre part la problematique secondaire est d’eviter au maximum d’extraire le contenu des jar.
#!/usr/bin/perl -w use strict; use Archive::Zip qw( :ERROR_CODES :CONSTANTS ); use Digest::MD5 qw(md5 md5_hex);; sub readjar { my $file = shift; my $set = {}; my $zip = Archive::Zip->new(); die 'read error' unless $zip->read($file) == AZ_OK; for my $m ($zip->membersMatching('.*\.class')) { my $name = $m->fileName(); my $md5 = md5($m->contents()); $set->{$name} = $md5; } return $set; } sub diffjar { my $file1 = shift; my $file2 = shift; my $fs1 = readjar($file1); my $fs2 = readjar($file2); for my $f (keys %$fs1) { if (defined $fs2->{$f}) { unless ($fs1->{$f} eq $fs2->{$f}) { print "$f differ\n"; } delete $fs2->{$f}; } else { print "$f only in $file1\n"; } } for my $f (keys %$fs2) { print "$f only in $file2\n"; } } diffjar(shift, shift);
#!/usr/bin/perl -w use strict; use diagnostics; use Archive::Zip qw( :ERROR_CODES :CONSTANTS ); use Digest::MD5 qw(md5 md5_hex);; sub readjar { my $file = shift; my $set = {}; my $zip = Archive::Zip->new(); die 'read error' unless $zip->read($file) == AZ_OK; for my $m ($zip->membersMatching('.*\.class')) { my $name = $m->fileName(); my $md5 = md5($m->contents()); $set->{$name} = $md5; } return $set; } sub diffjar { my $file1 = shift; my $file2 = shift; my $fs1 = readjar($file1); my $fs2 = readjar($file2); for my $f (keys %$fs1) { if (defined $fs2->{$f}) { unless ($fs1->{$f} eq $fs2->{$f}) { print "$f differ\n"; } delete $fs2->{$f}; } else { print "$f only in $file1\n"; } } for my $f (keys %$fs2) { print "$f only in $file2\n"; } } sub findjar { my $d = shift; my $dirset = {}; use File::Find (); # Set the variable $File::Find::dont_use_nlink if you're using AFS, # since AFS cheats. # for the convenience of &wanted calls, including -eval statements: use vars qw/*name *dir *prune/; *name = *File::Find::name; *dir = *File::Find::dir; *prune = *File::Find::prune; # Traverse desired filesystems File::Find::find({wanted => sub { my ($dev,$ino,$mode,$nlink,$uid,$gid); if ((($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_)) && /^.*\.jar\z/si ) { my $path = $name; $path =~ s/$d\/?//; $dirset->{$path} = $name; } }}, $d); return $dirset; } sub recurse_diffjar { my $dir1 = shift; my $dir2 = shift; my $ds1 = findjar($dir1); my $ds2 = findjar($dir2); for my $f (keys %$ds1) { if (defined $ds2->{$f}) { diffjar($ds1->{$f}, $ds2->{$f}); delete $ds2->{$f}; } else { print "$f only here $dir1\n"; } } for my $f (keys %$ds2) { print "$f only here $dir2\n"; } } unless (@ARGV) { print <<EOF; Usage: $0 file1.jar file2.jar $0 -r dir1 dir2 EOF } if ($ARGV[0] eq '-r') { my $opt = shift; recurse_diffjar(shift, shift); exit; } diffjar(shift, shift);
Ces programmes sont utilisés pour comparer massivement des jars les uns avec les autres.