Ich habe etwa 500 Zeichenfolgen und möchte in einem Verzeichnis nach den Dateien suchen, die diese Zeichenfolgen enthalten, und die Dateinamen abrufen, die die Zeichenfolgen enthalten. Bisher habe ich Folgendes verwendet:
find -name 'LYFNRE.*' -exec grep -f file1.txt {} \; -print
Das Problem besteht jedoch darin, dass eine Zeichenfolge in vielen Dateien enthalten sein kann. Aufgrund der enormen Ausgabemenge ist es daher schwierig herauszufinden, welche Zeichenfolgen vorhanden sind und welche fehlen. Können Sie mir helfen, die Zeichenfolgen mit den entsprechenden Dateinamen dort auszudrucken, wo sie gefunden wurden?
Antwort1
Sie sollten sich einfach grep
die Dateinamen zuweisen lassen. GNU grep
kann das:
grep -HFf ../strings.txt *
Sie erhalten eine Ausgabe, die etwa wie folgt aussieht:
[filename]:[matched_line]
...für jede Übereinstimmung mit jeder Datei im Verzeichnis. Sie können auch Zeilennummern abrufen:
grep -HnFf ../strings.txt *
...der bereitstellt...
[filename]:[line_number]:[matched_line]
Antwort2
Das Problem besteht darin, dass Sie jeweils nur eine Datei an übergeben grep
. Wenn grep
in der Befehlszeile eine einzelne Datei angezeigt wird, geht das Programm davon aus, dass Sie genau wissen, wo Sie suchen. Daher wird der Dateiname vor Übereinstimmungen nicht angezeigt.
Ein Trick, um grep
die Ausgabe eines Dateinamens immer zu erzwingen, besteht darin, auch „pass“ zu verwenden /dev/null
(wobei es nie eine Übereinstimmung geben wird). Einige Grep-Implementierungen haben dafür eine Option: -H
.
Zusätzlich können Sie -exec … {} +
anstelle von verwenden -exec … {} \;
, um das Programm für mehrere Dateien auf einmal auszuführen. Das ist schneller. Sie sollten trotzdem /dev/null
oder übergeben -H
, da es vorkommen kann, dass der Befehl für genau eine Datei aufgerufen wird, entweder weil es eine einzige passende Datei gibt oder weil es viele Übereinstimmungen gibt, die erfordern, dass grep
es mehrmals aufgerufen wird und einmal zufällig eine einzelne Datei betrifft.
find -name 'LYFNRE.*' -exec grep -f file1.txt /dev/null {} +
GNU grep und aktuelle BSD-Implementierungen (einschließlich OSX) unterstützen Optionen zum grep
rekursiven Aufruf ohne dass dies erforderlich ist find
.
grep -R --include='LYFNRE.*' -f file1.txt -H .
Alternativ können Sie rekursives Globbing in Ihrer Shell durchführen. In zsh funktioniert dies sofort. In bash müssen Sie es shopt -s globstar
zuerst ausführen und beachten, dass bash (anders als find
bei zsh) durch symbolische Links zu Verzeichnissen rekursiv vorgeht.
grep -f file1.txt /dev/null **/LYFNRE.*
Antwort3
verwenden Sie egrep:
egrep -n "str1|str2|str3" file_names
-n druckt die Zeilennummer in der spezifischen Datei, in der die Zeichenfolge gefunden wurde