Text- oder Quellcodedateien auf Ähnlichkeit prüfen unter Linux

mirrorManchmal überfällt mich der starke Drang nachzuforschen, wieviel von meinem vermittelten Wissen auch tatsächlich angekommen, gespeichert und wiedergegeben werden kann. Im Volksmund heisst dies „Prüfung“, im Mund der Lernenden „Folter“. Im Zeitalter der Kommunikation könnte es natürlich sein, dass Dateien weitergegeben werden. Als Beurteiler sollte man das herausfinden, so dass man diese Dateien wieder zurückgeben kann :)…

Eine der Möglichkeiten unter Linux ist der similarity-tester. Er kann Code in verschiedenen Programmiersprachen oder auch Text vergleichen. Als Argument übernimmt er eine Liste von Dateien für den Vergleich.

Angenommen, man hat die Dateinamen vorgeschrieben und alle Resultate lokal, so listet folgender Befehl die Ähnlichkeiten prozentual auf, absteigend geordnet.

sim_text -e -s -p `find . -name 'aufgabe.vb'`

Wer sich in die Optionen einarbeiten möchte, sei auf die Manpage verwiesen.

Eine weitere Möglichkeit wäre Simhash. Leider bin ich zu dumm es zu verstehen und für meine Bedürfnisse aufzurufen.

Hat jemand vielleicht eine noch komfortablere Lösung? Vielleicht auch für Binärdateien?

Zipdateien on-the-fly erstellen mit PHP

Das Problem

On-The-Fly An unserer Schule wird Moodle als LMS (Learning Management System) verwendet. Es eignet sich sehr gut um Unterrichtsunterlagen wie Skripts, Aufträge und Präsentationen zu publizieren und den Lernenden auf eine angenehme Art und Weise zur Verfügung zu stellen. In einigen Kursen gibt es sehr viele dieser Ressourcen (Dateien und Verzeichnisse) zum Download und alleine schon das Anklicken und Speichern nimmt einen grossen Teil des zur Verfügung stehenden Zeitbudgets ein.

Einzelne Ressourcen können von der Lehrperson unsichtbar gemacht werden und nicht alle Dateien eines Kurses stehen zum Download bereit. Die Ansicht ist also sehr individuell und kann sich schnell ändern. Die Dateien werden über eine Versionsverwaltung in das System eingespiesen und können sich so ausserhalb des Systems verändern. Leider verunmöglicht dies die offensichtliche Lösung, einfach ein statisches Zip-Archiv zum Download zur Verfügung zu stellen.

Screenshot Moodle

Die Lösung

Das Zip muss also dynamisch (im Speicher) generiert werden bei einem Aufruf. Fündig wurde ich bei der Klasse archive bei phpclasses.org. Neben Zip-Archiven kann sie auch tar’s, gzip’s und bzip2’s erzeugen. Ich habe einige, kleine Erweiterungen vorgenommen, die noch beschrieben werden.

Die Handhabung ist sehr einfach:

// Archivklasse einbinden:
require_once ('lib/archive.php');

// Objekt erzeugen. Das Argument bezeichnet den Dateinamen
$zipfile= new zip_file('Meine Zipdatei.zip');

// Die Optionen
$zipfile->set_options(array (
        'basedir' => "/home/me/toZip/", // Das Basisverzeichnis. Sonst wird der ganze Pfad von / an im Zip gespeichert.
        'followlinks' => 1, // Symlinks sollen berücksichtigt werden
        'inmemory' => 1, // Die Datei nur im Speicher erstellen
        'level' => 6, // Level 1 = schnell, Level 9 = gut
        'recurse' => 1, // In Unterverzeichnisse wechseln
        // Wenn zu grosse dateien verarbeitet werden, kannes zu einem php memory error kommen
        // Man sollte nicht über das halbe memory_limit (php.ini) hinausgehen
        'maxsize' => 12*1024*1024 // Nur Dateien die <= 12 MB gross sind zippen
));

// Alle Dateien im Verzeichnis /home/me/toZip/Stuff hinzufügen
// Alle ".doc" Dateien und alle Ordner im Verzeichnis /home/me/toZip/Letters hinzufügen
$zipfile->add_files(array("Stuff", "Letters/*.doc"));

// Alle ".tmp" dateien in Stuff ausschliessen
$zipfile->exclude_files("htdocs/*.tmp");

// Alle Dateien in ".svn" und "CVS" Verzeichnissen ausschliessen (Regular Expressions)
$zipfile->exclude_regexp_files('.*/CVS|.*/CVS/.*|.*/\.svn|.*/\.svn.*');

// Archiv erstellen
$zipfile->create_archive();

// Archiv zum Download anbieten
$zipfile->download_file();

// Oder speichern (vielen Dank an PHPler!!!)
$zipfile->save_file('myzip.zip', $path = '/tmp/');

Änderungen

Ich habe folgende Dinge gegenüber der original archive.php geändert:

  • Mittels exclude_regexp_files() können Dateien auf Grund von Regular Expressions ausgeschlossen werden.
  • Die maxsize Option erlaubt das Ausschliessen von Dateien die grösser sind als die angegebene Zahl in Byte.
  • Verzeichnisse unter Linux werden als Verzeichnisse behandelt (Bug?)
  • exclude_file() prüft, ob eine Datei ausgeschlossen würde

Dank PHPler lönnen nun auch mit der Methode save_file($filename, $path = '') inmemory zips als Dateien gespeichert werden.

Meine Version kann natürlich auch frei heruntergeladen werden.