[Perl] Verzeichnis rekursiv auslesen
|
Seitenanfang |
Hi @ all! Ich habe mir vorgenommen ein kleines Programm zu schreiben, dass die Temporären Ordner von Windows sowie diverse selbst wählbare Ordner leert. Das ganze soll geleert werden, sobald der Ordner eine gewisse Maximalgrösse überschreitet. Soweit so gut. Um die Grösse eines Ordners zu ermitteln, dachte ich mir, ich werde das Verzeichnis rekursiv auslesen und dann die Grössen der einzelnen Dateien im Verzeichnis/Unterverzeichnis addieren und ausgeben. Habe auch schon Verzeichnisse rekursiv mit PHP ausgelesen -> hat wunderbar funktioniert. Google hab ich auch schon bemüht, und vom Prinzip her würd ich sagen hab ich dasselbe wie das WWW Leider funktioniert das Ganze aber nicht (es werden nur Dateien mit einer zahl als Dateinamenanfang ausgelesen und auch nur vom 1. Ordner) und ich hab kein Plan wieso. Wie gesagt ist das ganze in Pearl geschrieben. Hier mal der Code:sub folder_size { $pfad = shift; print "PATH: ".$pfad."\n\n"; opendir(dir, $pfad); while($datei = readdir(dir)) { if($datei != "." && $datei != "..") { $pfadtotal = $pfad."/".$datei; if(-d $pfadtotal) { print "DIR: ".$pfadtotal."\n"; folder_size($pfadtotal); } else { #Grösse der Dateien ermitteln print "FILE: ".$pfadtotal."\n"; $groesse = -s $pfadtotal; $sizetotal += $groesse; } } } closedir(dir); $sizetotal = $sizetotal / 1024 / 1024; return ($sizetotal); } print $size = folder_size($start);
Datum: 12.08.2005-23:38

|
re: [Perl] Verzeichnis rekursiv auslesen
|
Seitenanfang |
Ich hab jetzt grad rausgekriegt, das es dafür n Modul gibt von Perl. "File::Find" nur leider spuckt google nix gescheites drüber aus, wie die Syntax von dem Ding ist. Also wie ich die Ordner angeben muss und wie ich mir die gesammt Ordnergrösse anzeigen lassen kann. Wäre froh wenn mir da jemand von euch helfen könnte! mfg CombatSheep
Datum: 12.08.2005-23:49

|
re: [Perl] Verzeichnis rekursiv auslesen
|
Seitenanfang |
| Hi, warum so kompliziert?
my $max = "104857600"; # 100MB my $size = `dir c:\WINDOWS\Temp`; $size =~ s/^.*Datei\(en\) (.*) Bytes.*$/$1/; $complete_size =~ s/\.//g; if($size gt $max) { `del c:\WINDOWS\Temp\*.*` }
Und fertig ist der Lack.Erklärung: Alle Zeilen der Ausgabe von dir werden in die Variable $size geschrieben. Man beachte, 0x0a und 0x0d (Zeilenumbruch) sind auch nur Zeichen. Ich suche mir die Stelle an der ausgegeben wird, wie viele Dateien im Verzeichnis stehen, und deren Gesamtgröße. Danach lösche ich die TausenderTrennpunkte raus und habe die Anzahl Bytes aller Dateien. Deine Maximalgröße legst einfach als String an, denn genau genommen ist ein String auch nur eine Zahl. Dann wird geprüft und gegebenenfalls das Verzeichnis geleert. -uw
Datum: 13.08.2005-03:27

|
re: [Perl] Verzeichnis rekursiv auslesen
|
Seitenanfang |
| Dein erstes Problem ist die Rueckgabe von $sizetotal. Du pruefst ob dein absoluter Pfad ein Verzeichnis ist und rufst dann rekursiv auf, aber Du speicherst den Rueckgabewert fuer den rekursiven Aufruf nicht. Dein 2. Problem ist die Umrechnung auf MByte in der rekursiven sub vor dem return(). Wenn Du die Werte wie oben mit $sizetotal += $groesse; zusammenrechnest, addierst Du MBytes zu Bytes, da der rekursive Aufruf ein schon in MByte umgerechnetes Ergebnis liefert. Dein 3. Problem ist das Du das Handle "dir" erst nach dem rekursiven Aufruf wieder schliesst. Das ist kein guter Stil, denn 1) Die Zahl der geoeffneten Handles ist dann proportional zur Anzahl der Unterverzeichnisse die Du auslesen musst. 2) Hast Du das Handle nicht als local deklariert, damit weisst Du mit jedem rekursiven Aufruf dem Handle einen neuen Wert zu, ohne das alte Verzeichnis zu schliessen - Das close() nach der Rekursion geht also auf ein ungueltiges Handle, da "dir" schon in der Rekursion ge-close(d) wurde. Dein 4. Problem ist der Vergleich von Dateinamen mit != denn das ist ein nummerischer Vergleich. Fuer Strings benutzt man "ne" (not equal) oder "eq" (equal). Weitere Tips: * Gewoehne Dir an deine Variablen am Anfang der sub mit my oder local zu deklarieren und auch zu initialisieren. Dann laeuft deine sub immer mit den gleichen Vorraussetzungen. * Verwende die Pragmas strict und warnings. Dann bekommst Du mehr Meldungen ueber potentielle Fehler. So.. Hier dann noch ein Variante deines Codes mit den oben aufgefuehrten Punkten sub folder_size { # Variablen initialisieren my $pfad = shift; local *DIR; my @dateien = (); my $pfadtotal = ''; my $groesse = 0; # Verzeichnis lesen opendir(DIR, $pfad); @dateien = readdir(DIR); closedir(DIR); # Addition oder Rekursion fuer alle gelesenen foreach my $datei (@dateien) { next if ( ($datei eq '.') || ($datei eq '..')); $pfadtotal = "$pfad/$datei"; if(-d $pfadtotal) { $groesse += folder_size($pfadtotal); } else { $groesse = -s $pfadtotal; } } # Rueckgabe in Bytes return ($groesse); } my $size = folder_size($start); # Umrechnen in MByte $size /= 1_048_576; print $size;
Datum: 13.08.2005-11:43

|
re: [Perl] Verzeichnis rekursiv auslesen
|
Seitenanfang |
Erstmal ein riesen Dankeschön! Vielen Dank für die vielen hilfreichen Tips! Jetzt funktioniert es fast! Die Rekursion klappt, es werden mir auch alle Dateien aufgelistet, nur leider stimmt was mit der Zusammenrechnung nicht. Das Verzeichnis das hier angegeben ist, ist 42.5MB gross. Leider gibt mir das Skript aber nur 14.7MB zurück. Woran könnte das liegen??
#Einbinden nötiger Module use strict; use warnings;sub folder_size { # Variablen initialisieren my $pfad = shift; local *DIR; my @dateien = (); my $pfadtotal = ''; my $groesse = 0; # Verzeichnis lesen opendir(DIR, $pfad); @dateien = readdir(DIR); closedir(DIR); # Addition oder Rekursion fuer alle gelesenen foreach my $datei (@dateien) { next if ($datei eq '.' || $datei eq '..'); print "DATEI: $pfad\n"; $pfadtotal = "$pfad/$datei"; if(-d $pfadtotal) { print "VERZEICHNIS: $pfadtotal\n"; $groesse += folder_size($pfadtotal); } else { $groesse = -s $pfadtotal; } } # Rueckgabe in Bytes return ($groesse); } my $start = "D:/styles"; my $size = folder_size($start); # Umrechnen in MByte $size = $size / 1024 / 1024; print $size;
Datum: 13.08.2005-19:22

|
Ups... Typo..
|
Seitenanfang |
das muss natuerlich
$groesse += -s $pfadtotal; heissen
Datum: 13.08.2005-20:30

|
re: [Perl] Verzeichnis rekursiv auslesen
|
Seitenanfang |
Vielen Dank! Es funktioniert einwandfrei! mfg CombatSheep
Datum: 13.08.2005-22:28

|
re: [Perl] Verzeichnis rekursiv auslesen
|
Seitenanfang |
| Hallo, als Erweiterung der interessanten Fragestellung: Ich möchte in allen Unterverzeichnissen Dateien mit wenigen, anzugebenden Endungen in eine zip-Datei kopieren und erst dann die Dateien löschen, also verschieben. Dies soll unter Beibehaltung der Pfadstruktur geschehen, damit ich bei Bedarf die Dateien wieder zurückkopieren kann. Wie kann ich da vorgehen?
Datum: 13.08.2005-12:07

|
re: [Perl] Verzeichnis rekursiv auslesen
|
Seitenanfang |
| Du solltest Dir mal das Modul Archive::Zip anaschauen...
Datum: 15.08.2005-06:34

|
re: [Perl] Verzeichnis rekursiv auslesen
|
Seitenanfang |
| Ja, danke. Kann ich machen. Weil ich Anfänger bin, hoffte ich mit meiner Frage an einen Codeschnipsel zu kommen.
Datum: 15.08.2005-11:14

|
re: [Perl] Verzeichnis rekursiv auslesen
|
Seitenanfang |
| Codesnippets sind immer bei der Modul-Dokumentation dabei:http://search.cpan.org/~smpeters/Archive-Zip-1.16/lib/Archive/Zip.pod
Datum: 15.08.2005-12:36

|