Am Dienstag, 12. November 2002 20:31 schrieb Bernd Brodesser: Moin moin Bernd, erstmal: Meine/n Anerkennung und besonderen Dank an Dich für diese Deine jedenfalls nach meinem Verständnis in Form *und* Inhalt *vorbildliche* Hilfe!
wenn ich mit grep in Verzeichnissen mit sehr vielen Dateien, z.B. meinem News-Spool, suchen lassen will, bekomme ich immer die Fehlermeldung "Die Argumentliste ist zu lang".
Wißt Ihr dafür 'n "Gegenmittel"?
Ist doch wohl klar, kürzere Argumentliste.
Ja ja, sicher, aber wieso denn, hatte doch nur...
Dabei ist zu beachten, daß die shell etwaige Wildcards wie * ersetzt.
...jo, genau, ein * hintendrangemacht? ;-))
Wenn Du z.B ein Verzeichnis hast mit
$ ls
bar baz foo foobar
Na ja, wie gesagt, es geht (hauptsächlich) um meinen News-Cache 'meines' Newsreaders 'Pan', was ein (Unter)Verzeichnis, ~/../.pan/messages/cache, dies selbst jedoch ohne (weitere) Unterverzeichnisse, ist, in dem letzterer alle kompletten Postings (die mit Body's), momentan 9264 Stück, mit den Message-ID's als, also ziemlich langen, Dateinamen, ablegt. Und in dem ich immer mal was zu suchen habe. Und zwar entweder, weil der Reader (noch) keine Volltextsuche kann, nach bestimmten Textteilen. Oder, um den Cache zu aktualisieren gleich auszudünnen - wegen der sonst ziemlich lang werdenden Ladezeit - (z.B.) über den Date-Header nach bestimmten Postings gleich Dateie(namen)n, um die dann löschen...wozu sich nun noch 'ne 'Zusatzfrage' ;-) ...->
dann macht die shell aus
$ grep irgendwas *
grep irgendwas bar baz foo foobar
grep hat keine Chance zu erkennen, daß Du ursprünglich nur ein * eingegeben hast. Für grep ist es das gleiche, als wenn Du gleich
$ grep irgendwas bar baz foo foobar
eingegeben hättest. Das kann man sogar soweit treiben, wenn Du
$ grep f*
sagst, dann macht die shell daraus:
grep foo foobar
es wird somit in der Datei foobar nach dem String foo gesucht. Die shell interpretiert nicht, sie ersetzt nur. Natürlich nur mit Dateien, die es im Verzeichnis gibt.
Wenn es nun sehr viele Dateien sind, die auf dem Muster mit * zutreffen, dann kann es passieren, daß die Zeile zu lang wird. Die Länge ist aber begrenzt. Es kommt zu der Fehlermeldung.
...ok., denke mal, dass ich das jetzt zumindest 'einigermassen' :-) verstanden habe....
Also mußt Du was aufteilen. Es gibt verschiedene Möglichkeiten, etwa:
find . -type f -exec grep -H SUCHWORT {} \;
hat den Nachteil, daß für jede einzelne Datei grep angeschmissen wird. Bei so langen Listen wird es wohl langsam. Das -H von grep bewirkt, daß auch der Dateiname mit ausgegeben wird. Ohne -H würde nur der gefundene String ausgegeben. Damit wirst Du wahrscheinlich nicht viel anfangen können.
Wenn Du nur die Datei wissen willst, aber nicht den String, so kanst Du anstelle des -H ein -l setzen.
...jou! Genau das war's, äh, bzw. damit habe ich's nun 'immerhin' schon mal geschafft, die Dateinamen auf den Bildschirm zu bekommen. Aber!, von wegen "Zusatzfrage": Wie kann ich diesen Befehl jetzt noch erweitern, die Dateien auch gleich in ein anderes Verzeichnis verschoben oder 'wenigstens' kopiert zu kriegen?? Hab's mit 'ner Pipe, also | cp -a /path noch hintendran, probiert, geht aber leider nicht. :-(
Eine andere Möglichkeit ist die Zusätzliche Verwendung von xargs
find . -type f -print0 | xargs -0 grep SUCHWORT
funktioniert wunderbar, nur Du wirst die gleiche Probleme haben, wie bisher, da xargs wieder eine genausolange Zeile baut. Das kann man aber auch umgehen. Dazu must Du mal man xargs lesen. Ist bei mir aber nicht sonderlich ergiebig. Vielleicht gibt es noch weitere Dokumentation. info brachte aber nichts, in /usr/share/doc/packages stand auch nichts und xargs --help ist denkbar knapp.
Hm, fürchte, das ist...
Das -0 im Zusammenhang mit dem -print0 von find bewirkt, daß als Trenner zwichen den Namen nicht das Leerzeichen genommen wird, sondern das ASCII-Zeichen mit dem Wert 0. Also nicht das Zeichen 0, das den Dezimalwert 48, bzw. Hexadezimalwert 30 hat sondern das Zeichen NUL mit dem (Hexa)Dezimalwert 0. Das Ganze deshalb, weil es sonst zu Problemen kommt, wenn es Dateien gibt, die in ihren Namen ein Leerzeichen gibt.
...(sowieso) 'zu hoch' für mich ja nur Amateur.
Eine einfache andere Möglichkeit wäre:
grep -r Suchwort .
Hier ist es grep, daß rekursiv sucht. Ich habe es aber nicht ausprobiert, wie es auf Riesenverzeichnisse wirkt, da ich keine solche habe.
Es wird dann auch in allen Unterverzeichnissen gesucht, und es gibt Probleme, wenn es darin nicht nur Normale Dateien und Verzeichnisse gibt. Bei einer named Pipe (FIFO) bleibt es auf jeden Fall hängen, bei symlinks kann es passieren, daß es deadloops gibt.
Tja, bringt hier jedenfalls wieder nur "Die Argumentliste ist zu lang"
Eine einfache Möglichkeit ist natürlich den * einzuschränken. Also etwa a* und dann b* usw. bzw. 1* und dann 2* usw.
Na ja, ziemlich umständlich, ne'? Jedenfalls wär's schon schön, wenn's doch noch 'ne bequemere...in einem Rutsch... :) Auf jeden Fall aber noch einmal vielen Dank für Deine bisher ja schon grosse Mühe...!,
Bernd
Grüsse und tschö Jürgen -- Wer das erste Knopfloch verfehlt, kommt mit dem Zuknöpfen nicht zurande. Goethe