Kann ich find und grep in einer Zeile verwenden?

7

Ich habe eine Verzeichnisstruktur basierend auf Ereignissen.

In diesen Fällen habe ich einen Dateityp, der ein Muster enthält oder nicht, nach dem ich suchen muss. Die positiven Ergebnisse möchte ich in einer separaten Datei speichern.

Mein erster Ansatz war:

find . /EVENT*/'filename' | grep 'searchtext' head -2 > error_file

aber das scheint nicht zu funktionieren. Mir wurde gesagt , dass es nicht möglich zu kombinieren findund grepauf diese Weise, so wie muss ich es tun?

Jos
quelle
Beachten Sie, dass Sie hier ( ungefähr ; dies ist technisch nicht 100% korrekt, aber nahe genug für eine Annäherung erster Ordnung, um Ihnen eine Vorstellung davon zu geben, was tatsächlich vor sich geht) zuerst ausführen find . /EVENT*/'filename'und dann alles ausführen , was dieser Befehl auf seinem Standard druckt Ausgabe (die im Fall findvon standardmäßig eine Liste von Dateinamen ist) und übergeben Sie diese als Standardeingabe an den Befehl grep 'searchtext' head -2(was nicht viel Sinn macht, da grepstdin bei gegebenen Dateinamen nicht angezeigt wird ) Standardausgabe von grepin die Datei umleiten error_file.
Ein CVn
Wenn ich es richtig interpretiere, sieht es so aus, als ob es eine globartige Erweiterung in gibt /EVENT*/'filename'. Ich bin mir nicht sicher, wie ich das machen soll find, und AFAIK bashkann das nicht. Alle bisherigen Antworten haben dies verpasst.
Sparhawk

Antworten:

14

Hier ist ein allgemeines Muster:

find /directory/containing/files -type f -exec grep -H 'pattern_to_search' {} +

Hier werden zunächst findalle Dateien im Verzeichnis durchsucht, die die erforderlichen Dateien enthalten. Sie können auch Platzhalter verwenden, z. B. *.txtum nur nach Dateien zu suchen, die mit enden .txt. In diesem Fall wäre der Befehl:

find /directory/containing/files -type f -name "*.txt" -exec grep -H 'pattern_to_search' {} +

Nachdem wir die erforderlichen Dateien gefunden haben, suchen wir nach dem gewünschten Muster in diesen Dateien mit -exec grep -H 'pattern_to_search' {} +( -Hdruckt den Dateinamen, in dem das Muster gefunden wird). Hier können Sie sich vorstellen {}, dass sie die zu durchsuchenden Dateien enthalten und +am Ende mit verwendet -execwerden müssen, -execdamit sie nur einmal gegabelt werden, dh grepso suchen, als ob der Befehl lautet grep -H 'pattern_to_search' file_1.txt file_2.txt file_3.txt.

heemayl
quelle
Okay - ich denke, das ist der Grund: superuser.com/questions/140689/… Wenn nur eine Datei in der Übereinstimmung vorhanden ist, druckt grep den Dateinamen nicht, sodass durch Hinzufügen /dev/nullsichergestellt wird, dass mindestens zwei vorhanden sind, wenn es eine gibt Spiel. Die Verwendung -Hscheint jedoch eine normativere, weniger verrückte Methode (und weniger Typisierung) zu sein. Ich würde es
dahingehend
Ich denke auch, dass Sie brauchen '{}', nicht einfach {}. Sonst bekomme ich missing argument to -exec.
Goldlöckchen
@goldilocks - das solltest du nicht zitieren müssen.
Mikeserv
@mikeserv Hmmmph, sieht aus wie es ein Fischschalenproblem ist - genau das gleiche unter Bash ist in Ordnung. Ich erinnere mich, dass ich vor einiger Zeit darüber verwirrt war. Ich glaube, es war, als ich anfing, Fisch als Standard zu verwenden.
Goldlöckchen
Ich würde auch eher einfache Anführungszeichen als doppelte Anführungszeichen
wählen
5

Eine andere gültige Methode ist:

 find /directory/containing/files -type f -print0 | xargs -0 grep "test to search"

Die Option print0 / -0 soll den Fall berücksichtigen, in dem Dateinamenzeichenfolgen Sonderzeichen (wie Leerzeichen) enthalten.

mdpc
quelle
Verwenden von -exec grep "test to search" {} +Handles Dateinamen mit Sonderzeichen ganz gut. Der einzige Grund, es nicht zu verwenden, ist, dass einige Systeme es nicht unterstützen.
AKHolland
3

Und noch eine Art und Weise, in nur einen einzigen Prozess (ohne find, -exec, xargs):

grep -r "test to search" /directory/containing/files

Na ja, mit GNU grep jedenfalls. :) :)

ETA: Da ich gebeten wurde, die grep --includeOption anzuzeigen, ist hier ein Analogon zu Heemayls Beispiel ("Sie können auch Platzhalter verwenden, z. B. * .txt, um nur nach Dateien zu suchen, die mit .txt enden"):

grep --include '*.txt*' -r "pattern to search" /directory/containing/files

Und während ich bearbeite, sind dies Alternativen, keine Drop-In-Ersetzungen: Diese Befehle lesen (reguläre) Dateien über Symlinks. (Sie werden jedoch nicht durch mit Symlinks verknüpfte Verzeichnisse wiederholt -R. Dazu benötigen Sie.) Sie lesen auch Sockets, Named Pipes und Gerätedateien ( -D skipkönnen jedoch hinzugefügt werden, ähm, überspringen Sie diese). Und es gibt keine Möglichkeit grep, die Wirkung von findOptionen wie zu erzielen -mtime -2. Wenn Sie diese brauchen - verwenden Sie find. Wenn Sie dies nicht tun, würde ich behaupten, dass dies grepeine gute Alternative ist.

Der Sidhekin
quelle
2
Dies unterscheidet sich darin, dass grep dann alle Dateien durchsucht (was manchmal keinen Spaß macht) und nicht diejenigen, die einem findMuster entsprechen.
Goldlöckchen
3
@goldilocks Sicher, wenn Sie haben ein findMuster. Außer, Sie können auch Muster geben grep -r; am häufigsten --exclude=GLOB(oder --include=GLOB) und --exclude-dir=GLOB, obwohl ich denke, dass Sie manchmal brauchen -D skipund / oder -I. Aber sicher, wenn Sie haben -mtime -2oder so, brauchen Sie das find. grep -rist eine andere Option, kein Ersatz.
Die Sidhekin
@ The Sidhekin: Sie sollten Ihren Beitrag bearbeiten, um die Option --include hinzuzufügen. Dies ist die richtige Antwort.
Jopasserat
@jopasserat Wirklich? Was --includeaber? Der ursprüngliche Ansatz, der nicht funktioniert, hat keine angegeben. Obwohl ich denke, ich könnte ein Analogon zu Heemayls Beispiel hinzufügen, das man auch verwenden kann…
The Sidhekin
In Anbetracht der Frage von OP scheint er eine bestimmte Art von Dateien zu haben, in denen er suchen kann. Also würde ich sagen --include = 'pattern' mit einem Muster, das mit dem übereinstimmt, was er will.
Jopasserat
0

Ich gehe davon aus, dass Sie durch Textdateien nach einem bestimmten Muster suchen und durch Unterverzeichnisse rekursieren müssen. Wenn Sie GNU grep verwenden, ist es ziemlich einfach:

cd /to/the/top/level    
grep -r "PatternToSearch" *

Stattdessen -rkönnen Sie -Roder verwenden--recursive

Sie müssen Anführungszeichen verwenden, wenn Ihr Suchmuster Leerzeichen enthält.

Es gibt viele Optionen für GNU grep. Geben grep --helpSie einfach ein und Sie werden begeistert sein!

Hüpfender Hase
quelle
Wie können Sie grep bitten, nur Dateien anzuzeigen, die einem bestimmten Muster entsprechen? Sagen wir, Dateinamenerweiterung? Mit diesem Vorschlag wird grep in jeder Datei im Dateisystem unter diesem Ordner angezeigt: Dies ist nicht das, was die Frage versucht.
GreenAsJade
So etwas wie * .log sollte reichen. Übrigens wäre der Silver Searcher dafür praktischer und schneller:ag SearchWord FilePattern
Hopping Bunny