wie grep große Anzahl von Dateien?

7

Ich versuche grep 40k Dateien im aktuellen Verzeichnis und ich bekomme diesen Fehler.

%Vor%

Wie macht man normalerweise grep Tausende von Dateien?

Danke Upendra

    
upendra 09.05.2014, 19:54
quelle

4 Antworten

23

Das macht David traurig ...

Jeder ist bisher falsch (außer anubhava ).

Shell-Scripting ist nicht wie jede andere Programmiersprache, da ein großer Teil der Zeileninterpretation von der Stärke der Shell herrührt, die sie interpoliert, bevor der Befehl tatsächlich ausgeführt wird.

Nehmen wir etwas Einfaches:

%Vor%

Mit set -x können Sie sehen, wie die Shell den Glob interpoliert und diesen dann als Eingabe an den Befehl zurückgibt. % Co_de% zeigt auf die Zeile, die tatsächlich vom Befehl ausgeführt wird.

Sie können sehen, dass der Befehl > das echo nicht interpretiert. Stattdessen greift die Shell auf * und ersetzt sie durch die Namen der übereinstimmenden Dateien. Dann und nur dann führt der Befehl * den Befehl tatsächlich aus.

Wenn Sie 40K plus Dateien haben und echo , dann erweitern Sie das grep * auf die Namen dieser 40.000 plus Dateien, bevor * sogar eine Chance hat, ausgeführt zu werden, und das ist die Fehlermeldung / usr / bin / grep: Zu lange Argumentliste kommt von.

Glücklicherweise hat Unix einen Weg um dieses Dilemma zu umgehen:

%Vor%

Das grep findet alle find . -name "*.kaks" -type f -maxdepth 1 Dateien und das *.kaks nur die Dateien im aktuellen Verzeichnis. Der -depth 1 stellt sicher, dass Sie nur Dateien und kein Verzeichnis auswählen.

Der Befehl -type f leitet die Namen der Dateien in find und xargs fügt die Namen der Datei an den Befehl xargs an. % Co_de% hat jedoch einen Trick im Ärmel. Er weiß, wie lange der Befehlszeilenpuffer ist, und führt den grep -f A01/genes.txt aus, wenn der Befehlszeilenpuffer voll ist, und übergibt dann eine weitere Reihe von Dateien an den xargs . Auf diese Weise wird grep möglicherweise drei- oder zehnmal ausgeführt (abhängig von der Größe des Befehlszeilenpuffers) und alle unsere Dateien werden verwendet.

Leider verwendet grep Whitespace als Trennzeichen für die Dateinamen. Wenn Ihre Dateien Leerzeichen oder Tabulatoren enthalten, haben Sie Probleme mit grep . Glücklicherweise gibt es eine andere Lösung:

%Vor%

Das xargs bewirkt, dass xargs die Namen der Dateien ausdruckt, die nicht durch Zeilenumbrüche getrennt sind, sondern durch das NUL-Zeichen. Der -print0 -Parameter für find sagt -0 , dass das Dateitrennzeichen nicht Leerzeichen ist, sondern das NUL-Zeichen. So behebt das Problem.

Sie könnten das auch tun:

%Vor%

Dies führt die xargs für jede gefundene Datei aus, anstatt xargs und führt nur grep für alle Dateien aus, die in der Befehlszeile eingefügt werden können. Der Vorteil davon ist, dass es die Schaleninterferenz vollständig vermeidet. Es ist jedoch möglicherweise nicht weniger effizient.

Was interessant wäre, ist zu experimentieren und zu sehen, welches effizienter ist. Sie können xargs verwenden, um Folgendes anzuzeigen:

%Vor%

Dies wird den Befehl ausführen und Ihnen dann sagen, wie lange es gedauert hat. Probieren Sie es mit dem grep und mit time aus und sehen Sie, welches schneller ist. Lass uns wissen, was du findest.

    
David W. 09.05.2014, 20:33
quelle
7

Sie können find mit grep wie folgt kombinieren:

%Vor%     
anubhava 09.05.2014 20:07
quelle
0

Sie können die rekursive Funktion von grep verwenden:

%Vor%

obwohl, wenn Sie nur kaks Dateien auswählen möchten:

%Vor%     
zmo 09.05.2014 19:58
quelle
0

Setzen Sie eine andere Schleife in Ihre äußere:

%Vor%

Übrigens, sind Sie daran interessiert, JEDES Vorkommnis in jeder Datei zu finden oder nur, wenn die Suchzeichenfolge einmal oder mehrmals dort existiert? Wenn es "gut genug" ist zu wissen, dass die Zeichenkette dort ein- oder mehrmals vorkommt, können Sie "-n 1" für grep angeben, und es wird nicht den Rest der Datei nach dem Finden der ersten Übereinstimmung lesen / durchsuchen, was möglicherweise Sparen Sie viel Zeit.

    
Mark Setchell 09.05.2014 20:01
quelle

Tags und Links