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

Calculating differences between the contents of a zip and a directory

by MilanorTSW (Beadle)
on Nov 02, 2012 at 06:56 UTC ( [id://1001921]=perlquestion: print w/replies, xml ) Need Help??

MilanorTSW has asked for the wisdom of the Perl Monks concerning the following question:

Greetings, fellow monks.

Suppose I have a zip file that includes file1, file2 and file3 and a directory that includes file1 and file2, different from the one in zip.

I want to write a Perl script that can point out that file3 does not exist in the directory and that file2 is different.

Now, I've tried implementing that with a MANIFEST-like file, but is there a more efficient solution?

Replies are listed 'Best First'.
Re: Calculating differences between the contents of a zip and a directory
by graff (Chancellor) on Nov 03, 2012 at 05:44 UTC
    I think the right tool for this job would be Archive::Zip. Here's one way to do what you described - you want to be able to compare file sizes, and when they match, you want to compare the CRC32 values, just to be sure.

    (And if you don't want to trust just the file-size and CRC comparisons, it would be easy enough, and some extra run-time, to test if file contents from the zip are equal to (eq) file contents from the directory. But that's probably overkill.)

    #!/usr/bin/perl use strict; use Archive::Zip; my $Usage = "$0 file.zip [test_path]\n (default test_path is '.')\n"; die $Usage unless ( @ARGV and -f $ARGV[0] ); my $zipfile = shift; my $testpath = shift || '.'; my $zip = Archive::Zip->new( $zipfile ) or die "Archive::Zip was unable to read $zipfile\n"; my ( @missing_from_path, @altered ); for my $member ( $zip->members ) { next if ( $member->isDirectory ); my $filepath = $member->fileName; if ( ! -f "$testpath/$filepath" ) { push @missing_from_path, $filepath; next; } if ( -s _ == $member->uncompressedSize ) { if ( open( my $testfile, '<', "$testpath/$filepath" )) { local $/; $_ = <$testfile>; close $testfile; my $testCRC = $zip->computeCRC32( $_ ); next if ( $testCRC eq $member->crc32 ); } else { warn "Unable to read $testpath/$filepath: $!\n"; } } push @altered, $filepath; } print "Comparing $zipfile to $testpath:\n"; if ( @missing_from_path ) { print " Missing files:\n"; print " $testpath/$_\n" for ( sort @missing_from_path ); } else { print " No files missing\n"; } if ( @altered ) { print " Altered files:\n"; print " $testpath/$_\n" for ( sort @altered ); } else { print " No altered files\n"; } =head1 NAME zip-check -- check zip file against directory contents =head1 SYNOPSIS zip-check [path/to/]file.zip [test_path] (default test_path is '.') =head1 DESCRIPTION This script will compare the contents of a given zip file against the contents of a given directory (current working directory by default). We check for two types of differences: - Files in the zip archive that are not found in the directory - Files found in both places, but having different contents (based on comparing their CRC32 values) (We do not report cases where the directory contains files that are not found in the zip archive.) =head1 AUTHOR David Graff <graff at ldc dot upenn dot edu> =cut

      Ah, many thanks.

      Now, I did think it could be possible to just compare sizes, but it wasn't completely trusted.

      I didn't think of CRC comparisons.

Re: Calculating differences between the contents of a zip and a directory
by Anonymous Monk on Nov 02, 2012 at 07:04 UTC

    Now, I've tried implementing that with a MANIFEST-like file, but is there a more efficient solution?

    Yeah, unzip ... and diff -ruN olddir unzippeddir

      Thanks, but I can't do that without unzipping the file, can I? Also, I would need for the script to transfer platforms, I'll have to use File::DirCompare or something similar instead.

        Thanks, but I can't do that without unzipping the file, can I?

        Not sure, I don't remember details of archive formats.

        Typically archiving programs support listing contents of archives , so if that is faster than unzipping, and sufficiently detailed for your analysis, go for it, Try It To See

        Also, I would need for the script to transfer platforms, I'll have to use File::DirCompare or something similar instead.

        You could do that. You could also install diff on the target machine :) whatever you need

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others taking refuge in the Monastery: (3)
As of 2024-04-16 03:55 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found