ZIP mit Perl

ZIP-Archive, Kompression & Expansion

ZIP ist in der Windows-Welt das meist verwendete Datei-Format für Archive. Mittlerweile bietet auch jedes Standard Linux-System Unterstützung für ZIP-Archive. Auf dieser Seite wird gezeigt, wie man mit Perl Dateien zu ZIP-Archiven komprimieren kann, und wie man ZIP-Archive wieder auspacken kann.
Perl Perl Scripts für CGI und Systemverwaltung
Vorbereitung ZIP-Software, Modul Archive, temporäre Arbeits-Verzeichnisse
System-Befehle Kopieren, Verschieben, Komprimieren, Expandieren, Löschen, ...
Kompression Verpacken von Dateien und Verzeichnissen zu ZIP-Archiven
Expansion Auspacken von ZIP-Archiven
Verwandte Themen Archive, Software, Module, ..

Vorbereitung für Perl @ ZIP

ZIP-Software Sie sollten unabhängig von Perl in der Lage sein, Dateien in ZIP-Archive zu komprimieren und wieder auszupacken. Dazu gibt es im Internet zahlreiche Programme, z.T. auch kostenfrei.

ZIP-Konsolen-Programme

Besonders wertvoll - weil leicht zu automatiseren - sind Konsolen-Programme, z.B. für Win-Systeme InfoZip.

Modul Archive::Zip

Dieses Perl-Modul wird für die ZIP-Unterstützung benötigt. Das 'Testprogramm' läuft fehlerfrei, wenn das Modul vorhanden ist, oder erzeugt eine Fehlermeldung Cant locate Archive in @INC . .

use Archive::Zip;

Details zur Feststellung, ob ein Perl-Modul geladen ist, im Kapitel Perl-Umgebung.

Installation von Archive::Zip

Auf Linux-Systemen erfolgt die Installation meist durch das Software Management Programm der Distribution, z.B. YAST für SuSE:
YAST | Software | Software installieren, wählen sie dann Suche nach perl und markieren sie das Archiv.
Compiler:
Alternativ benötigen sie den Quelltext des Moduls (z.B. von CPAN) und compilieren daraus selbst das Modul oder überhaupt eine komplett neue Perl-Version.

Auf Windows verwendet man für ActivePerl den Package Manager ppm
Öffnen sie eine Konsole (Eingabeaufforderung, cmd.exe ), starten sie ppm und installieren sie das Modul Archive:
C:\> ppm install Archive-Zip
Wenn das Modul bereits installiert ist, dann erhalten sie eine Meldung wie z.B. Package 'Archive-Zip' is already installed
Andernfalls wird das Modul installiert und ist anschließend sofort gebrauchsfertig. Automatisch wird auch die Dokumentation für das Modul in der Perl-Doku installiert..

Temporäres Archiv-Verzeichnis

Erstellen sie ein eigenes Arbeits-Verzeichnis für die Archiv-Arbeit, und darin je ein Verzeichnis für Kompression und Expansion, z.B. auf Linux
/home/test/zip/compress
/home/test/zip/expand
oder auf Windows
C:\zip\compress
C:\zip\expand
Test-Dateien:
Kopieren sie in das compress-Verzeichnis 1-2 reine Text-Dateien und 1 beliebige andere Datei, z.B. ein Bild testbild.jpg
Die Text-Dateien sollten ein paar Zeilen Text enthalten. Die Datei-Namen sollten keine Leerzeichen, Umlaute oder sonderzeichen enthalten.
Kopieren sie in das expand-Verzeichnis ein ZIP-Archiv, z.B. aus den Dateien des compress-Verzeichnisses hergestellt:
/home/test/zip/expand/archiv.zip
C:\zip\expand\archiv.zip
Nach Möglichkeit sollte man niemals am Original-Speicherplatz komprimieren / expandieren. Das kann bei Misserfolg Daten zerstören, und bietet wenig Übersicht.
Bei der Arbeit mit ZIP-Archiven reserviert man ein leeres Verzeichnis (expand) zur Aufnahme aller Dateien eines ausgepackten Archivs, ein weiteres (compress) zur Aufnahme aller Dateien und Unter-Verzeichnisse, welche zu einem Archiv komprimiert werden sollen.
Nur in diesen temporären Verzeichnissen wird tatsächlich komprimiert und expandiert. Das gesamte Rohmaterial (Dateien und Archive) wird vor der Arbeit dorthin kopiert, das Ergebnis wird nach der Arbeit an sein Ziel verschoben.

Pfad-Separator

Wenn Pfad-Texte ausschließlich innerhalb von Perl verwendet werden, dann kann man auch für Windows-Pfade das Standard Trennzeichen / verwenden, z.B.
C:/test/test.txt
In den nachfolgenden Beispielen dieser Seite werden Pfade auch für Systembefehle (copy ..) eingesetzt, dort muss das Separator-Zeichen des jeweiligen Systems eingesetzt werden, für Windows der \ Backslash. Da dieses Zeichen in Perl zur Maskierung von Sonderzeichen verwendet wird, muss man jeden \ in einem String mit einem zusätzlichen \ maskieren.

Arbeit mit System und externen Programmen

Perl harmoniert ausgezeichnet mit Konsolen-Programmen und System-Befehlen. Rechts ein Windows-Beispiel für die Zusammenarbeit mit den Programmen (zip, unzip) von InfoZip.
Das Beispiel wird hier gezeigt, weil es im Zusammenhang mit Archiven fast immer notwendig ist, Dateien und Verzeichnisse mit System-Befehlen zu verarbeiten.

Das Ziel des Beispiels bestand darin, systematische Änderungen an hunderten Dateien im Standard OpenDocument-Format (OpenOffice) vorzunehmen. Diese Dateien sind XML-Dateien und daher reiner Text, allerdings zu ZIP-Archiven gepackt.

Vorgaben / Verzeichnisse:
Die Perl-Programme befinden sich in $mypath, die Original-Archive *.odt im Pfad $path, das Arbeits-Verzeichnis in $tmppath
Variable $r erhält jeweils die Ausgabe (Antwort) der ausgeführten Anweisungen und wird nur zum Debuggen verwendet.
Arbeits-Schleife:
Das Arbeits-Verzeichnis $tmppath wird mit rmdir rekursiv (inkl. aller enthaltenen Objekte) gelöscht und danach mit mkdir neu (leer) angelegt.

Das Original-Archiv $path wird unter dem Standard-Namen test.zip in das Arbeits-Verzeichnis kopiert. Das Programm wechselt mit chdir in das Arbeits-Verzeichnis und expandiert das Archiv mit unzip
Danach wird das Archiv mit del gelöscht.

Das Programm wechselt in seinen eigenen Pfad $mypath und startet dort ein Arbeits-Programm text_ant.pl, welches die ausgepackten Dateien verarbeitet (Dieses Programm hat nichts mit Archiven zu tun und wird hier nicht gezeigt).

Nach Ausführung aller Arbeiten an den ausgepackten Dateien wechselt das Programm wieder in das Arbeits-Verzeichnis und komprimiert mit zip rekursiv (alle vorhandenen Dateien) zum Archiv fertig.zip

Danach wechselt das Programm wieder in seinen eigenen Pfad. Aus dem Pfad zum Original-Archiv $path wird mit einem Regulären Ausdruck der Pfad $dstpath erzeugt, danach wird das fertige Archiv dorthin kopiert.
Die gesamte Arbeit wird nur mit Kopien der Original-Daten ausgeführt. Der gezeigte Arbeits-Zyklus wird in einer Schleife wiederholt (hier nicht gezeigt), wobei $path alle vorhandenen OpenDocument-Dateien durchläuft.
Details dazu auf der Seite Perl @ Verzeichnisbaum (tree).

Das Programm ist Windows-spezifisch: Es verwendet Win-Programme (zip, unzip) mit spezieller Syntax, weiters ist die Syntax der Systembefehle (copy ..) und das Pfad-Separator-Zeichen unterschiedlich zu Linux !
my $path = "c:\\roh\\archiv.odt";
my $tmppath = "c:\\tmp\\zip";
my $mypath = "c:\\perltest";
my $r;

# Arbeits-Schleife
my $cmd="rmdir /S/Q $tmppath";
$r=qx($cmd);
$r=qx("mkdir $tmppath");

$cmd="copy $path $tmppath\\test.zip";
$r=qx($cmd);
chdir($tmppath);
$cmd="unzip test.zip";
$r=qx($cmd);
$cmd="del test.zip";
$r=qx($cmd);

chdir($mypath);
$cmd="text_ant";
$r=qx($cmd);

chdir($tmppath);
$cmd="zip -r fertig.zip *.*";
$r=qx($cmd);

chdir($mypath);
my $dstpath=$path;
$dstpath=~s/roh/fertig/;
$cmd="copy $tmppath\\fertig.zip $dstpath";
$r=qx($cmd);

Details zur Ausführung von System-Befehlen (hier qx ) mit Perl.

Dateien zu ZIP-Archiven komprimieren

Deklarieren sie die Verwendung von Perl-Modul Archive::Zip und erzeugen sie ein Archiv-Objekt (hier $zip ).

Wenn das Programm (hier mit chdir ) in das Arbeits-Verzeichnis wechselt, dann werden im Archiv relative Pfade gespeichert, ansonsten (meist unerwünscht) absolute Pfade.

Alle im Arbeits-Verzeichnis enthaltenen Objekte $obj werden untersucht.
Details zum Durchforsten eines Verzeichnis-Baums (tree) mit readdir auf der Seite Perl @ Verzeichnisbaum (tree)

Das vereinfachte Beispiel verarbeitet keine Verzeichnisse, sondern nur Dateien. In der Praxis werden an Stelle des Kommentars # Verzeichnis alle enthaltenen Sub-Verzeichnisse und deren Objekte rekursiv durchlaufen.

Mit Methode addFile wird ein Objekt (Datei) in das ZIP-Archiv übernommen.

Zuletzt wird das Arbeits-Verzeichnis geschlossen und das fertige Archiv als Datei (hier im Pfad $dst ) gespeichert. Bei Erfolg wird $ok=0 zurückgegeben, ansonsten ein Fehler-Code.
use Archive::Zip;
my $zip = Archive::Zip->new();

my $workdir = "/home/test/zip/compress";
my $dst = "/home/test/zip/archiv.zip";

chdir($workdir);
opendir(my $dh,$workdir);
my($obj,$member);
while ($obj = readdir($dh)) {
if ($obj=~/^\.{1,2}$/) {next;}
if (-d $obj) {
# Verzeichnis
}
else {
$member = $zip->addFile($obj);
}
closedir $dh;
my $ok = $zip->writeToFileNamed($dst);
Details zum Modul Archive::Zip finden sie in der Original Perl-Dokumentation unter Modules | Archive | Zip und im Internet.  

ZIP-Archive auspacken

Deklarieren sie die Verwendung von Perl-Modul Archive::Zip und erzeugen sie ein Archiv-Objekt (hier $zap ).

Der Inhalt des Archiv-Objekts wird mit Methode read gelesen. Bei Erfolg wird $ok=0 zurückgegeben.

Methode members gibt ein Array aller im Archiv enthaltenen Objekte zurück. Jedes Element von @members ist selbst ein Hash. Alternativ erhält man mit Methode memberNames ein Array der Objekt-Namen als Strings.

In einer Schleife werden alle Objekte des geöffneten Archivs durchlaufen.
Mit Methode extractMember wird jedes Objekt als Datei gespeichert, und zwar im einfachsten Fall ohne weitere Angaben mit seinem Original-Dateinamen.
use Archive::Zip;
my $zap = Archive::Zip->new();

my $workdir = "/home/test/zip/expand";
my $src = "$workdir/archiv.zip";

chdir($workdir);
my $ok = $zap->read($src);
my @members = $zap->members();
my $element;
foreach $element(@members) {
$zap->extractMember($element);
}
Wenn im Archiv Unter-Verzeichnisse oder ganze Dateibäume enthalten sind, dann werden benötigte Verzeichnisse automatisch erzeugt.  

Verwandte Themen

Das Perl-Modul Archive::Zip bietet noch viele weitere Möglichkeiten. Sehen sie sich die Original Perl-Dokumentation dazu an, wenn sie mit ZIP-Archiven professionell arbeiten wollen.
Das Modul Archive::Tar bietet analoge Funktionen zur Verarbeitung der vor allem auf Linux verbreiteten Tar-Archive.
Das Perl-Modul OpenOffice bietet interessante Möglichkeiten zur direkten Arbeit mit OpenDocument Dokumenten. Dabei entfällt der Umweg, die Dateien (wie im Beispiel dieser Seite) auszupacken, zu bearbeiten und danach wieder zu verpacken.
Details dazu bei CPAN.
Die Arbeit mit Archiven bedeutet meist auch das Durchforsten ganzer Datei-Bäume. Ein detailliert erklärtes Beispiel finden sie auf der Seite Perl @ Verzeichnisbaum (tree) Linux bietet für die Verarbeitung verschiedener Archive u.a. die shell-Programme bzip2, bunzip2, gzip, gunzip, tar, zip, unzip
Hilfe erhalten sie mit den Befehlen man oder info, z.B.
man zip

Perl-Module

Perl bietet eine große Anzahl zusätzlicher Module mit spezialisierten Funktionen.
Am Server ihres Web-Providers können sie keine Module installieren. Für den eigenen Gebrauch können die Module jedoch praktische Funktionen enthalten, die evtl. viel Arbeit sparen.

Beispiele für Stichworte bei der Suche nach nützlichen Modulen:
archive, compress, openoffice, zip, ..