Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much

Decoding .z and .gz files

by blackadder (Hermit)
on Mar 26, 2007 at 10:59 UTC ( [id://606549] : perlquestion . print w/replies, xml ) Need Help??

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

Dear Monks

I am trying to decode compressed files mainly of .gz and .z types!

To start off with I wrote this scripts to handle .gz file;
#! c:/perl/bin/perl.exe # By me- March 2007 use strict; use Archive::Tar; #use Archive::Zip; system(cls); my $tar = Archive::Tar->new(); opendir (DIR, $ARGV[0]) || die "\nHey, gimme a path to work with pleas +e!\n"; my @dirs = readdir (DIR); unlink ("$ARGV[0]\\modinfo.txt"); foreach my $dir (@dirs) { next if ($dir eq '.' || $dir eq '..'); $tar->read("$ARGV[0]\\$dir", 1); @_ = $tar->list_files(); for my $modinfo (@_) { next unless ($modinfo =~ /modinfo.txt/); $tar->extract_file( $modinfo, "$ARGV[0]\\modinfo.txt"); open(FILE,"$ARGV[0]\\modinfo.txt") || die "D'oh: need a lot of + help here!"; chomp (my @stuff = <FILE>); for my $line (@stuff) { next unless ($line =~ /vx/); $line =~ s/^\s+//; $line =~ /(\w+)\s+(\w+)\s+(\w+)\s+(\d+)\s+(\d+)\s+(\w+)\s+ +\((.+)\)$/; printf "%s, %s,%s,%s,%s,%s,%s,(%s)\n",$dir,$1,$2,$3,$4,$5, +$6,$7; } } }
which works fine on the ".gz" but it can't handle ".z" files!

I tried Archive::Zip to no avail!

I began to look around here for posts that have delt with similar issues. The advice I got (tho it seems) that I should be using Comprees::Zlib. So I tried the following bit of code just to test, however its didn't work (i.e. it returned noise - exaclty similar to opening any binary file with a basic text editor)!
#! c:/perl/bin/perl.exe use strict; use Compress::Zlib ; my $gz = gzopen("c:\\eee.tar.z", "rb") || die "Cannot open c:\\eee.tar +.z: $gzerrno\n" ; while ($gz->gzreadline($_) > 0) { print ; }
Can someone please help me out or shed a light on what I need to do in order to extract files from .z files?


Replies are listed 'Best First'.
Re: Decoding .z and .gz files
by grinder (Bishop) on Mar 26, 2007 at 12:04 UTC

    .Z files (uppercase) are compressed using a simple LZW algorithm. You can unpack them with Compress::LZW or Compress::LZF.

    update: oops, it says in the documentation that Compress::LZW does not support .Z files..

    use Compress::LZF ':compress'; my $file = shift; open my $fh, '<', $file or die "Cannot open $file for input: $!\n"; local $/ = undef; my $decompressed = decompress(<$fh>);

    Update: hmmm, I don't actually have any .Z files around, so I made one, and the above code fails to decompress it, as does Compress::Zlib's uncompress function. Sigh.

    Do you have a decompress binary lying around? Or you don't and you really have to do this in Perl? Because if you did, it would probably be much faster to pay the system call and let the binary do the decompression.

    • another intruder with the mooring in the heart of the Perl


      its a small "z" not a Capital "Z"

      Still I Tried Compress::LZF as suggested however I got this error
      C:\Perl>perl -I c:/perl/bin compressed data corrupted (size mismatch) at line 9, <$fh> chunk +1.

        Nevertheless, I suspect it's supposed to be a capital Z. I don't suppose you could paste in a hex dump of the first 256 characters or so... It may reveal that the compression isn't ".z" or ".Z" at all.

        UPDATE: Wow, just wow. A hex dump would look more like this:

        0000000: 4120 6865 7820 6475 6d70 2077 6f75 6c64 A hex dump would 0000010: 206c 6f6f 6b20 6d6f 7265 206c 696b 6520 look more like 0000020: 7468 6973 3a0a this:.

        Of course, your tools may differ from xxd.


Re: Decoding .z and .gz files
by Burak (Chaplain) on Mar 26, 2007 at 13:57 UTC
    According to, you have to use an external binary:
    The Archive::Tar module can optionally use Compress::Zlib (via the IO::Zlib module) to access tar files that have been compressed with gzip. Unfortunately tar files compressed with the Unix compress utility cannot be read by Compress::Zlib and so cannot be directly accesses by Archive::Tar.

    If the uncompress or gunzip programs are available, you can use one of these workarounds to read .tar.Z files from Archive::Tar
      IT WORKED,....Thanks for all the replies

      I used "Gunzip.exe" on the .z files!

      Here is the full code
      #! c:/perl/bin/perl.exe # # By a PerlMonk # use strict; use Archive::Tar; my $tar = Archive::Tar->new(); system(cls); opendir (DIR, $ARGV[0]) || die "\nInvalid path $ARGV[0]!\n"; my @path = readdir (DIR); for my $comp_file (@path) { next if ($comp_file eq '.' || $comp_file eq '..'); my $temp_path = "$ARGV[0]\\$comp_file"; `gunzip.exe $temp_path` if ($comp_file =~ /\.z$/); my $tar = Archive::Tar->new(); $tar->read("$temp_path", 1); @_ = $tar->list_files(); for my $compressed (@_) { next unless ($compressed =~ /modinfo.txt/); $tar->extract_file( $compressed, "$ARGV[0]\\extracted_modinfo. +txt"); open(FILE,"$ARGV[0]\\extracted_modinfo.txt") || warn "$!: Cann +ot access temp file\n"; chomp (my @vx_data = <FILE>); for my $vx (@vx_data) { next unless ($vx =~ /vx/); $vx =~ s/^\s+//; $vx =~ /(\w+)\s+(\w+)\s+(\w+)\s+(\d+)\s+(\d+)\s+(\w+)\s+\( +(.+)\)$/; printf "%s, %s,%s,%s,%s,%s,%s,(%s)\n",$comp_file,$1,$2,$3, +$4,$5,$6,$7; } close (FILE); unlink ("$ARGV[0]\\extracted_modinfo.txt"); } }
      Thanks again "feel an urge for a donation now! :-)"
Re: Decoding .z and .gz files
by kyle (Abbot) on Mar 26, 2007 at 14:05 UTC
Re: Decoding .z and .gz files
by Moron (Curate) on Mar 26, 2007 at 14:52 UTC
    Both formats have had two binary treatments rather than one. First they were archived into tar format and then zipped into gz or z format. So for the second case you still need to unzip from z format first but moreover you then need to extract the human-readable file(s) from the resulting tar file using Archive::Tar just as you did in the .gz case where you performed both translations correctly.


    Free your mind

      Spot on. Thanks indeed