Shell-Befehl zum Suchen von Dateien, die ein Wort enthalten, aber nicht das zweite Wort

1128
Sandeep K Gujje

Alles

Ich habe die beiden folgenden Dateien in meinem Linux-Rechner und wollte die Datei herausfinden, die "word1" und nicht "word99" enthält.

file1.txt word1 word2 word3 word4 word5  file2.txt word1 word2 word3 word99 

Ich habe den folgenden Befehl für Dateien verwendet, die "word1" enthalten, aber ich konnte keine Informationen finden, wie er geändert werden kann, um die Dateinamen zu erhalten, die "word1" aber nicht "word99" enthalten.

find . -name '*.*' -exec grep -r 'word1' {} \; -print > output.txt 

Alle Hinweise wären hilfreich.

Danke, Sandy

4

3 Antworten auf die Frage

4
Santios
 $ grep -lr 'word1' * | xargs grep -L 'word99' file1.txt 

woher:

 -l, --files-with-matches Only the names of files containing selected lines are written to standard output. -R, -r, --recursive Recursively search subdirectories listed. -L, --files-without-match Only the names of files not containing selected lines are written to standard output. 

Im ersten Teil des Befehls vor der Pipe erhalten wir:

 $ grep -lr 'word1' *  file1.txt file2.txt 

Der obige Befehl analysiert rekursiv die Dateien in den Unterverzeichnissen und listet die Dateien auf, die das Wort word1(dh file1.txtund) enthalten file2.txt.

Später im zweiten Teil | xargs grep -L 'word99'sendet die Pipe file1.txtund file2.txtals Eingabe, an xargsdie sie grepals Argumente weitergibt. greplistet dann die Datei auf, die nicht word99die -LOption enthält, dh file1.txt.

Wir brauchen xargshier, da wir im ersten Teil des Befehls file1.txtund file2.txtals Ausgabe auf dem Standardausdruck erhalten. Wir müssen den Inhalt dieser Dateien analysieren und nicht die Zeichenfolgen file1.txtund file2.txt.

Der folgende Befehl liefert auch dasselbe Ergebnis (kehrt die Art und Weise um, in der wir die Zeichenfolgen suchen / ausschließen):

 $ grep -Lr 'word99' * | xargs grep -l 'word1' file1.txt 
`grep -r… *` wird fast immer besser geschrieben `grep -r… .`. Die Sternchenversion wird hässlich, wenn sich zu viele Dateien im aktuellen Verzeichnis befinden usw. Eric vor 7 Jahren 1
0
John1024

Dadurch werden Dateien gefunden, die Folgendes enthalten word1:

$ find . -name '*.*' -type f -exec grep -q 'word1' {} \; -print ./file1.txt ./file2.txt 

Diese findet Dateien, die enthalten, word1aber nicht word99 :

$ find . -name '*.*' -type f -exec grep -q 'word1' {} \; '!' -exec grep -q 'word99' {} \; -print  ./file1.txt 

So speichern Sie die Ausgabe in einer Datei:

find . -name '*.*' -type f -exec grep -q 'word1' {} \; '!' -exec grep -q 'word99' {} \; -print >output.txt 

Der Test -exec grep -q word99 {} \;gibt True für Dateien mit zurück word99. Wir setzen !davor, um den Rückgabewert zu negieren. Somit ! -exec grep -q word99 {} \;liefert True für Dateien, die Sie nicht haben word99. Das !ist in einfache Anführungszeichen gesetzt, da es sich bei aktivierter Historienerweiterung !um ein Shell-aktives Zeichen handeln kann.

Anmerkungen:

  1. Die -qOption wurde hinzugefügt grep, um es leise zu machen. Mit -qgrep wird der korrekte Beendigungscode gesetzt, aber es werden keine übereinstimmenden Zeilen in stdout angezeigt.

  2. Der -type fTest wurde hinzugefügt, findsodass nur die Namen normaler Dateien zurückgegeben werden.

Danke John für die Antwort, aber wenn ich eine Suche in allen Ordnern machen muss (rekursiv). Wetter Hinzufügen nur ein "-r" funktioniert? Sandeep K Gujje vor 7 Jahren 0
@SandeepKGujje `find` selbst führt eine rekursive Suche in allen Ordnern durch. John1024 vor 7 Jahren 0
0
TOOGAM

Der Titel Ihrer Frage lautet "Dateien mit einem Wort". In Ihrer Frage erwähnen Sie jedoch "erhalten die Dateinamen, die ein Wort enthalten". Das sind verschiedene Dinge. Zum Glück sind beide ziemlich einfach, deshalb zeige ich es euch einfach.

So finden Sie Dateien, die ein Wort enthalten:

grep -iR "word1".

Der -i sagt, den Fall zu ignorieren. Das -R ist rekursiv (dh es werden Unterverzeichnisse durchsucht). (Großbuchstaben werden von OpenBSD dokumentiert und ähneln ls, daher bevorzuge ich das über -r.) Der Zeitraum gibt an, wo er anfangen soll.

So finden Sie Dateinamen, die ein Wort enthalten:

finden . -iname " word1 "

Der -iname ist eine von "name" zwischen Groß- und Kleinschreibung unterschiedene Version.

Der Zeitraum gibt an, wo Sie suchen sollen. Das aktuelle Verzeichnis ist oft eine gute Wahl.

Hinweis: Sie haben in einem Ihrer Beispiele auf " . " Verwiesen . Das war großartig für DOS und normalerweise gut für Microsoft Windows, aber für Unix-Umgebungen eine schlechte Angewohnheit. Wenn ich das sehe, denke ich, dass Sie mit Windows vertraut sind. Nun, verstehen Sie, dass in Windows "FIND" (oder "find") Text in Dateien findet. Unix unterscheidet sich: "grep" sucht nach Text in Dateien und "find" nach Dateinamen.

Um nun das Wort 99 auszuschließen und in eine Textdatei einzufügen, fügen Sie den folgenden Text hinzu:

| grep -v word99 >> output.txt

Dies ist der Pipe-Key, fast immer Shift-Backslash.

Wenn Sie also beides ausführen möchten, verwenden Sie Folgendes:

grep -iR "word1". | grep -v word99 >> output.txt
find. -iname " word1 " | grep -v word99 >> output.txt

Der Teil vor dem Pipe-Zeichen führt einen Befehl aus und sendet die Ausgabe in eine Unix-Pipe. Dann wird der Inhalt von der Pipe an die Standardeingabe des nächsten Befehls gesendet. grep -v prüft die empfangenen Standardeingaben und schließt aus, was Sie möchten. grep -v sendet die verbleibenden Ergebnisse an seine Standardausgabe. Der >> leitet die Standardausgabe des vorherigen Befehls an das Ende der angegebenen Textdatei weiter.

Der Grund, warum Sie im Befehl "find" keine dokumentierten Optionen zum Ausschließen von Text sehen, ist, dass Unix sehr stark mit der Idee entworfen wurde, einfachere Programme zu erstellen und die Piping-Technik zu verwenden, um komplizierte Effekte zu verursachen. In Microsoft-Umgebungen war der alte Microsoft-Code insbesondere bei der Verarbeitung von Pipes umständlicher, weshalb Programme grundsätzlich versuchten, mehr Funktionalität in jedes Programm zu integrieren. Auf der einen Seite scheint das für den Endbenutzer einfacher zu sein (da alles eingebaut ist), aber dieser Ansatz ist nicht konsistent. Wenn Sie mit Unix arbeiten, haben Sie keine Angst vor dem Paspeln: Wenn Sie sich erst einmal daran gewöhnt haben, werden Sie vielleicht die Dinge sehr vereinfachen, aber Sie können Ihre einfachen Werkzeuge in vielen Situationen verwenden und brauchen dies nicht einfache Techniken immer wieder neu erlernen (für jedes unterschiedliche Programm).