Ein find soll Dateien in verschieden tiefen Verzeichnissen nach einem bestimmten Muster finden. Das ist soweit klar, Ausgegeben sollen aber von dieser Selektion die _tiefsten_ Verzeichnisse und ihre Größe, also die Summe der Dateien in diesem Verzeichnis. Also find zeigt zB diese Dateien an: /a/b/c/d /a/b/c/e /a/b/c/f /a/b/c/g h/i/j h/i/k Eine Liste dieser Art soll erstellt werden (In Bytes): 67024837 ,c 47986207 ,i Mein Hauptproblem ist die unterschiedliche Tiefe der Verzeichnisse, da ich mit "du" die Tiefe genau angeben muss. Al
Hallo, Am Fre, 20 Okt 2006, Al Bogner schrieb:
Ein find soll Dateien in verschieden tiefen Verzeichnissen nach einem bestimmten Muster finden. Das ist soweit klar, [..] Eine Liste dieser Art soll erstellt werden (In Bytes): 67024837 ,c 47986207 ,i
Mein Hauptproblem ist die unterschiedliche Tiefe der Verzeichnisse, da ich mit "du" die Tiefe genau angeben muss.
==== #! /usr/bin/perl -w use strict; use File::Find; my %dirs; sub wanted { if(-d $_ ## hier weitere Bedingungen ) { $dirs{$File::Find::name} = undef; } } sub getsize { return `du -bs "$_[0]"`; } scalar @ARGV or push(@ARGV, "."); File::Find::find({wanted => \&wanted}, @ARGV); foreach my $d (keys %dirs) { ### aussortieren: $dirs{$d} = getsize($d) if ( scalar grep(/^$d/, keys %dirs) eq 1 ); } foreach(sort keys %dirs) { print $dirs{$_} if $dirs{$_}; } exit(0); ==== Eine weitere Bedingung waere z.B. "&& m/foo/", d.h. nur Verzeichnisse die 'foo' im Namen (nicht Pfad) enthalten. Frag ggfs. nach. Besonders falls Bedingungen als Option uebergeben werden sollen. Der entscheidende Schritt, fuer den mir auf der Shell nix einfiel, ist das 'aussortieren'. Gibt es Unterverzeichnisse, so gibt es diese im Hash und somit liefert das 'grep' mehr als ein Ergebnis. Nur fuer die ohne weitere Unterverzeichnisse (bei denen das 'grep' nur ein Ergebnis liefert) wird dann 'getsize' aufgerufen. Und dessen Ergebnis als "Wert" des Eintrags verwendet. Alle anderen "Werte" sind "undef", worauf sich die Ausgabe stuetzt ;) HTH, -dnh -- [Wahlrecht in Appenzell-Innerrhoden] [..] erzählte die Geschichte, einer Frau aus der Gegend, die die Einführung des Wahlrechts beklagte: "Früher habe ich meinen Männern gesagt, was sie wählen sollen, heute muß ich selbst hinlatschen."
Hallo, Am Fre, 20 Okt 2006, David Haller schrieb:
Am Fre, 20 Okt 2006, Al Bogner schrieb:
Ein find soll Dateien in verschieden tiefen Verzeichnissen nach einem bestimmten Muster finden. Das ist soweit klar, [..] Eine Liste dieser Art soll erstellt werden (In Bytes): 67024837 ,c 47986207 ,i
Mein Hauptproblem ist die unterschiedliche Tiefe der Verzeichnisse, da ich mit "du" die Tiefe genau angeben muss.
Nachtrag, da mir das 'delete' gestern Nacht nicht einfiel: ==== #! /usr/bin/perl -w use strict; use File::Find; my %dirs; sub wanted { if(-d $_) { $dirs{$File::Find::name} = undef; } } sub getsize { return `du -bs "$_[0]"`; } scalar @ARGV or push(@ARGV, "."); File::Find::find({wanted => \&wanted}, @ARGV); foreach my $d (keys %dirs) { if ( scalar grep(/^$d/, keys %dirs) eq 1 ) { $dirs{$d} = getsize($d); } else { delete($dirs{$d}); } } print values %dirs; exit(0); ==== -dnh -- No, it's a small country on the South American Ivory Coast, just to the left of the Caucasus, with penguin wool and yucca meat as primary exports. -- H. Ekker on the question if Austria is in Europe
Am Freitag, 20. Oktober 2006 17:15 schrieb David Haller: Hallo David, erstmal vielen Dank für dein Perl-Script! Vielleicht ist die Aufgabenstellung zu wenig klar, aber irgendwo/-wie in meinen Scripts hatte ich ähnliches schon mit der Bash gelöst. Mir fällt aber nicht mehr genau ein, zu welchem Anlaß das war. Vermutlich war es aber für deine Begriffe auch zu umständlich, aber es brachte das gewünschte Ergebnis. In einem simplen "Einzeiler" geht es mit Perl a auch nicht. Ich würde daher dazu ein paar zusätzliche Fragen stellen, weil ich aus dem Shellscript nicht Perl aufrufen möchte (ja, ja ich sollte gleich mit Perl anfangen ;-) ) find "$2" -follow -type f -name "*.txt" ... | sort ... Ich weis nicht, wie ich die Dateigröße (nicht Ordnergröße) liste, also etwa so 3500000 /a/b/c 4500000 /a/b/d 1200000 /e/f Nehmen wir an, ich will das eventuell sowieso in einer Datei protokollieren. Im nächsten Schritt wird dann diese Datei so manipuliert, dass folgendes übrigbleibt. Vermutlich kann man das mit awk machen. 3500000 b 4500000 b 1200000 e Eventuell kann man die beiden Teile auch in einer Pipe mit xargs abarbeiten. Jetzt fällt mir auch wieder ein, wie ich das damals mit der Gruppierung gemacht habe, ich denke ich habe damals Teile in einer MySQL-DB verarbeitet, weil damals von dort die Daten kamen. Beim Gruppieren stehe ich nun mit der Bash an. Ich kann aber fast nicht glauben, dass da Perl der einzige Ausweg ist um das zu erreichen: 8000000 b 1200000 e Ich bin auch gerade am überlegen, ob ich nicht sowieso das Suchergebnis in der MySQL-DB haben will, dann wäre jedenfalls das Gruppieren kein Problem mehr. Die Performance ist vernachlässigbar, ich denke das Suchergebnis ergibt so um die 500-1000 Dateien. Al
Hallo, Am Sam, 21 Okt 2006, Al Bogner schrieb:
Am Freitag, 20. Oktober 2006 17:15 schrieb David Haller: erstmal vielen Dank für dein Perl-Script! Vielleicht ist die Aufgabenstellung zu wenig klar, aber irgendwo/-wie in meinen Scripts hatte ich ähnliches schon mit der Bash gelöst. Mir fällt aber nicht mehr genau ein, zu welchem Anlaß das war. Vermutlich war es aber für deine Begriffe auch zu umständlich, aber es brachte das gewünschte Ergebnis. In einem simplen "Einzeiler" geht es mit Perl a auch nicht. Ich würde daher dazu ein paar zusätzliche Fragen stellen, weil ich aus dem Shellscript nicht Perl aufrufen möchte (ja, ja ich sollte gleich mit Perl anfangen ;-) )
So bald das perl-script mal laeuft ist es vermutlich deutlich schneller. Und mit so wenigen Modulen startet das script selbst hier flott. Und (s.u.) das Filtern, v.a. auf die Verzeichnistiefe ist mit Shell-Mitteln nur *sehr* muehsam zu machen.
find "$2" -follow -type f -name "*.txt" ... | sort ...
Ich weis nicht, wie ich die Dateigröße (nicht Ordnergröße) liste,
also etwa so 3500000 /a/b/c 4500000 /a/b/d 1200000 /e/f
Nehmen wir an, ich will das eventuell sowieso in einer Datei protokollieren.
Im nächsten Schritt wird dann diese Datei so manipuliert, dass folgendes übrigbleibt. Vermutlich kann man das mit awk machen.
3500000 b 4500000 b 1200000 e
Aeh, jetzt verwirrst du mich. Du schriebst, du wolltest nur jew. die "tiefste" Verzeichnisebene bearbeiten (jetzt: und dort die Groessen der *.txt Dateien summieren?)...
Eventuell kann man die beiden Teile auch in einer Pipe mit xargs abarbeiten.
Jetzt fällt mir auch wieder ein, wie ich das damals mit der Gruppierung gemacht habe, ich denke ich habe damals Teile in einer MySQL-DB verarbeitet, weil damals von dort die Daten kamen.
Eben.
Beim Gruppieren stehe ich nun mit der Bash an. Ich kann aber fast nicht glauben, dass da Perl der einzige Ausweg ist um das zu erreichen:
8000000 b 1200000 e
Wie jetzt? Willst du doch nur die Summe der Groessen der *.txt unterhalb von b und e? Das ginge dann auch wieder mit Shell-Mitteln.
Ich bin auch gerade am überlegen, ob ich nicht sowieso das Suchergebnis in der MySQL-DB haben will, dann wäre jedenfalls das Gruppieren kein Problem mehr. Die Performance ist vernachlässigbar, ich denke das Suchergebnis ergibt so um die 500-1000 Dateien.
Also, beschreibe doch bitte mal so klar wie moeglich, was du machen willst. Und zwar nicht Schritt fuer Schritt, sondern z.B. so: * Startbedingungen: Gegeben sein ein Verzeichnisbaum mit u.a. *.txt-Dateien. Zusatzfragen: - Duerfen die *.txt-Dateien Symlinks sein? Wenn ja, soll den Links gefolgt werden? - Darf der Baum Symlinks enthalten? - Darf der Baum ueber mehrere Dateisysteme gehen? - ...? - soll das Verzeichnis dem Script als Argument uebergeben werden koennen? - soll das Dateimuster dem Script als Argument uebergeben werden koennen? * Gewuenschtes Ergebnis: - Summiere die Groesse der *.txt-Dateien? Wie genau? · Verzeichnisweise? · Mit welcher Ausgabe? Verzeichnisweise? · Wenn sortiert: wie? Nach Dateiname oder Groesse? · ...? · [und fuer jede darueberliegende Ebene?] Oder was? Solange du keine gescheite Problembeschreibung lieferst, so lange kann man "ewig" an einem einzelnen Problem eines "falschen" Algorithmus herumbasteln, ein Problem, das sich womoeglich beim "richtigen" Algorithmus "in Wohlgefallen" aufloesen kann. Sei versichert, dass ich stets auch einen "Shell"-Variante ueberlege, aber eben nur bis zu einem gewissen Aufwand... ;) -dnh -- Life is sexually transmitted, and terminal...
participants (2)
-
Al Bogner
-
David Haller