2009-05-26 8 views
0

Ich schreibe ein Perl-Skript (in Windows), das File :: Find verwendet, um ein Netzwerk-Dateisystem zu indizieren. Es funktioniert großartig, aber es dauert sehr lange, das Dateisystem zu crawlen. Ich dachte, es wäre schön, irgendwie eine Checksumme eines Verzeichnisses zu bekommen, bevor man es durchquert, und die Prüfsumme stimmt mit der Prüfsumme überein, die bei einem vorherigen Lauf genommen wurde, nicht durch das Verzeichnis. Dies würde eine große Anzahl von Verarbeitungen überflüssig machen, da sich die Dateien in diesem Dateisystem nicht oft ändern.Kann ich die MD5sum eines Verzeichnisses mit Perl bekommen?

Auf meiner AIX-Box, verwende ich diesen Befehl ein:

csum -h MD5 /directory 

, das so etwas wie dies zurück:

5cfe4faf4ad739219b6140054005d506 /directory 

Der Befehl nur sehr wenig Zeit in Anspruch nimmt:

time csum -h MD5 /directory 
5cfe4faf4ad739219b6140054005d506 /directory 

real 0m0.00s 
user 0m0.00s 
sys  0m0.00s 

Ich habe hat CPAN nach einem Modul durchsucht, das dies tut, aber es sieht so aus, als ob alle Module mir die MD5sum für jede Datei in einem di geben würden Pfarramt, nicht für das Verzeichnis selbst.

Gibt es eine Möglichkeit, die MD5sum für ein Verzeichnis in Perl oder sogar in Windows zu bekommen, da ich einen Win32-Befehl von Perl aufrufen könnte?

Vielen Dank im Voraus!

Antwort

3

Können Sie nur die letzten geänderten Daten der Dateien und Ordner lesen? Sicher, das wird schneller sein als MD5 zu bauen?

+0

+1 ist das AIX-Tool wahrscheinlich nur Hashing die Metadaten – Dave

+0

Die Manpage für csum ist irreführend: "Der Befehl csum berechnet einen Nachrichtenauszug für die angegebenen Dateien mit dem angegebenen Hash-Algorithmus. Dies bietet eine zuverlässige Möglichkeit zur Überprüfung der Dateiintegrität." - Das lässt mich nicht glauben, dass es Metadaten hasht. – BrianH

+0

Obwohl es sein könnte - nicht bestreiten Ihren Anspruch, ich sage nur die Manpage nicht so klingen. – BrianH

2

Um eine Prüfsumme zu bekommen, müssen Sie die Dateien lesen, das bedeutet, dass Sie das Dateisystem durchlaufen müssen, das Sie zurück in das gleiche Boot bringt, aus dem Sie herauskommen wollen.

+0

So ist es ein Merkmal von AIX, dass die „csum“ lässt Befehl das Dateisystem nicht mehr laufen? Vielleicht nutzt es den modifizierten Zeitstempel auf dem dir? Weil das Beispiel, das ich oben veröffentlicht habe, "0" Sekunden auf einem 1,5 Terabyte Dateisystem nahm. – BrianH

+2

Der csum-Befehl arbeitet mit Dateien, ein Verzeichnis ist eine Datei, daher wird das Verzeichnis als Datei überprüft (d. H. Nicht rekursiv). Fügen Sie eine Datei in ein Unterverzeichnis von dem ein, mit dem Sie csum ausführen. Sie sollten immer noch die gleiche Prüfsumme sehen. Sie können auch versuchen, einige Daten an eine bereits vorhandene Datei anzuhängen, die die Prüfsumme ebenfalls nicht ändern sollte (Verzeichnisse enthalten nur Namen, Metadaten werden in Inodes gespeichert). –

+0

Okay - Ich habe eine Datei in einem niedrigeren Unterverzeichnis berührt, und Sie haben Recht, die Prüfsumme hat sich nicht geändert. Aber selbst das würde mir helfen - wenn ich im untersten Unterverzeichnis bin, würde ich gerne checksum dieses Verzeichnis schreiben, denn dann muss ich nicht alle Dateien in diesem Verzeichnis lesen. Irgendeine Möglichkeit, das mit Perl zu machen? – BrianH

1

Von dem, was ich weiß, können Sie nicht eine MD5 eines Verzeichnisses. md5sum auf anderen Systemen beschwert sich, wenn Sie ein Verzeichnis bereitstellen. csum gibt höchstwahrscheinlich einen Hash des Verzeichnisdateiinhalts des Verzeichnisses der obersten Ebene und nicht durch den Baum.

Sie können die geänderten Zeiten für die Dateien packen und sie Hash, wie Sie, indem Sie so etwas wie dies mag:

sub dirModified($){ 
    my $dir = @_[0]; 
    opendir(DIR, "$dir"); 
    my @dircontents = readdir(DIR); 
    closedir(DIR); 

    foreach my $item (@dircontents){ 
     if(-f $item){ 
      print -M $item . " : $item - do stuff here\n"; 
     } elsif(-d $item && $item !~ /^\.+$/){ 
      dirModified("$dir/$item"); 
     } 
    } 
} 

Ja es einige Zeit zu laufen nehmen.

1

Zusätzlich zu den anderen guten Antworten, lassen Sie mich hinzufügen: Wenn Sie eine Prüfsumme möchten, dann wählen Sie bitte eine checksum algorithm anstelle eines (broken!) hash function verwenden.

Ich glaube nicht, dass Sie keine kryptografisch sichere Hash-Funktion in Ihrem Datei-Indexer benötigen - stattdessen brauchen Sie eine Möglichkeit zu sehen, ob es Änderungen in den Verzeichnis-Listen gibt, ohne die gesamte Auflistung zu speichern. Prüfsummenalgorithmen tun das: Sie geben eine andere Ausgabe zurück, wenn die Eingabe geändert wird. Sie könnten es schneller machen, da sie einfacher sind als Hash-Funktionen.

Es stimmt, dass ein Benutzer ein Verzeichnis auf eine Weise ändern konnte, die von der Prüfsumme nicht erkannt würde. Ein Benutzer müsste die Dateinamen jedoch absichtlich ändern, da normale Änderungen der Dateinamen (mit hoher Wahrscheinlichkeit) unterschiedliche Prüfsummen ergeben. Muss man sich dann vor diesem "Angriff" schützen?

Man sollte immer die Folgen jedes Angriffs berücksichtigen und die geeigneten Werkzeuge auswählen.