Dateinamen vor übereinstimmender Zeile anzeigen

282

Wie kann ich grepden Dateinamen vor den übereinstimmenden Zeilen in seiner Ausgabe anzeigen?

Vivek
quelle
2
Bitte sagen Sie Ihre grep-Versiongrep --version
Kent
3
Kent, grep --versionist das der Befehl, um die Grep-Version zu kennen? Wenn ja, funktioniert es nicht. Es konnte kein anderer Befehl gefunden werden, um die grep-Version zu kennen.
Vivek
2
gute Frage, aber 'Os Version' ist ein verwirrendes Beispiel Dateiname
HaveAGuess
1
Das Betriebssystem und die Version spielen hier keine Rolle.
MD XF
grep 'pattern' *
user0

Antworten:

430

Versuchen Sie diesen kleinen Trick, um zu glauben grep, dass es sich um mehrere Dateien handelt, sodass der Dateiname angezeigt wird:

grep 'pattern' file /dev/null

So erhalten Sie auch die Zeilennummer:

grep -n 'pattern' file /dev/null
Prüfer
quelle
6
Ja, es hat funktioniert. Können Sie mir bitte sagen, welche Bedeutung das Hinzufügen /dev/nulldieses Befehls hat?
Vivek
55
Wenn grepmehrere Dateinamen enthalten sind, werden die Dateinamen vor dem Abgleich automatisch angezeigt, bei einer einzelnen Eingabedatei wird der Dateiname jedoch weggelassen. Durch die Verwendung /dev/nullals zusätzliche Eingabedatei grep"denkt", dass es sich um mehrere Dateien handelt, aber / dev / null ist natürlich leer, so dass es nicht in der Übereinstimmungsliste angezeigt wird.
Scrutinizer
32
Die Verwendung von / dev / null ist ein cleverer Trick, aber ich denke, der Vorschlag unter dem Flag -H ist eine bessere Antwort.
JohnQ
22
OK, aber die -HOption für grep ist nicht Teil von POSIX, und das verwendete Betriebssystem ist Solaris 10, wobei weder das Standard-grep noch die POSIX-kompatible Version von grep die -HOption haben.
Scrutinizer
4
Dies ist wichtig, wenn Sie grep mit find verwenden, z. B. find . -name foo -exec grep pattern {} \;wenn viele Dateien fooin Ihrem Unterverzeichnis benannt sind und findimmer noch grepeine einzelne Datei zur Bearbeitung vorhanden ist. Der /dev/nullTrick scheint in allen Linux / Osx-Varianten zu funktionieren, die ich ausprobiert habe, also ein großes Lob! Hinweis Ich denke, das -Hist sauberer, aber wie unten erwähnt, wird es mit Ihrer Version von möglicherweise nicht unterstützt grep.
Jon V
296

Wenn Sie die Optionen haben -Hund -nverfügbar sind ( man grepist Ihr Freund):

$ cat file
foo
bar
foobar

$ grep -H foo file
file:foo
file:foobar

$ grep -Hn foo file
file:1:foo
file:3:foobar

Optionen:

-H, --mit Dateiname

Drucken Sie den Dateinamen für jede Übereinstimmung. Dies ist die Standardeinstellung, wenn mehr als eine Datei durchsucht werden muss.

-n, - Zeilennummer

Stellen Sie jeder Ausgabezeile die 1-basierte Zeilennummer in der Eingabedatei voran. (-n wird von POSIX angegeben.)

-Hist eine GNU - Erweiterung, sondern -nwird von POSIX spezifiziert

Chris Seymour
quelle
3
Nein, -Hwird hier nicht unterstützt.
Vivek
1
Unterstützt, aber es gibt immer grep: file: Keine solche Datei oder Verzeichnis
pal4life
2
funktioniert auf Ubuntu -H und -n. Wahrscheinlich mit allen neueren Versionen von * nix
tgkprog
1
Ich habe jahrelang damit gekämpft, ohne abends zu denken, dass es diese Möglichkeiten gibt!
GreenSaguaro
45

Kein Trick nötig.

grep --with-filename 'pattern' file

Mit Zeilennummern:

grep -n --with-filename 'pattern' file
MD XF
quelle
3
@codeforester Ich kenne keine anderen greps, also weiß ich es nicht.
MD XF
2
Cool ! Dies funktionierte für Linux. Wenn Sie einen Mac verwenden, können Sie Coreutils mit Brew installieren. Und denken Sie daran, PATH = "/ usr / local / opt / coreutils / libexec / gnubin: $ PATH" zu Ihrer .bashrc
zw963
2
Dies hat (auch) in MinGW funktioniert (1.0.17, glaube ich).
Peter Mortensen
Es funktioniert bei mir mit dem eingebauten Mac grep (2.5.1-FreeBSD). Um das alternative grep von Homebrew zu verwenden, können Sie es auch ausführen brew install grepund dann einfach verwenden ggrep. PATH muss nicht geändert werden.
Wunder
5

Wie wäre es damit, was ich teilweise dank dieses Beitrags erreichen konnte?

Sie möchten mehrere Dateien finden, beispielsweise Protokolle mit unterschiedlichen Namen, aber einem Muster (z. B. filename=logfile.DATE), in mehreren Verzeichnissen mit einem Muster (z /logsapp1, /logsapp2. B. ). Jede Datei hat ein Muster, das Sie erfassen möchten (z. B. "init time"), und Sie möchten das Muster "init time"jeder Datei haben, aber wissen, zu welcher Datei sie gehört.

find ./logsapp* -name logfile* | xargs -I{} grep "init time" {} \dev\null | tee outputfilename.txt

Dann outputfilename.txtwäre das so etwas wie

./logsapp1/logfile.22102015: init time: 10ms
./logsapp1/logfile.21102015: init time: 15ms
./logsapp2/logfile.21102015: init time: 17ms
./logsapp2/logfile.22102015: init time: 11ms

Allgemein

find ./path_pattern/to_files* -name filename_pattern* | xargs -I{} grep "grep_pattern" {} \dev\null | tee outfilename.txt

Erläuterung:

find Der Befehl durchsucht die Dateinamen anhand des Musters

Dann xargs -I{}leitet Pipe die findAusgabe an die um{}

welches die Eingabe für sein wird grep ""pattern" {}

Dann der Trick, um grepdie Dateinamen anzuzeigen\dev\null

und schließlich schreiben Sie die Ausgabe in Datei mit tee outputfile.txt

Dies funktionierte für mich in grepVersion 9.0.5 Build 1989.

Lejuanjowski
quelle
3
Oder einfach mit findfind ./path_pattern/to_files -type f -name "files*.log" -exec grep -Hn pattern {} \;
Martin
1

Dies ist eine geringfügige Änderung gegenüber einer früheren Lösung. Mein Beispiel sucht nach stderr-Umleitung in Bash-Skripten: grep '2>' $(find . -name "*.bash")

Richard Jessop
quelle
-7
grep 'search this' *.txt

arbeitete für mich, um alle .txt-Dateien zu durchsuchen (geben Sie natürlich Ihren eigenen Suchwert ein).

MagicMojo
quelle