Ich habe dies häufig verwendet. Die Verbesserung, die ich erreichen möchte, besteht darin, Echo-Dateinamen zu vermeiden, die nicht übereinstimmen grep. Besserer Weg, dies zu tun?

 for file in `find . -name "*.py"`; do echo $file; grep something $file; done 

Kommentare

Antwort

 find . -name "*.py" -exec grep something {} \; -print  

druckt den Dateinamen nach den übereinstimmenden Zeilen.

 find . -name "*.py" -exec grep something /dev/null {} +  

druckt den Dateinamen vor jeder übereinstimmenden Zeile (wir fügen /dev/null für den Fall hinzu, dass es nur eins Übereinstimmende Datei als grep druckt den Dateinamen nicht, wenn nur eine Datei zum Suchen übergeben wurde. Die GNU-Implementierung von grep hat alternativ eine -H -Option dafür.

 find . -name "*.py" -exec grep -l something {} +  

druckt nur die Dateinamen der Dateien mit mindestens einer übereinstimmenden Zeile.

Um den Dateinamen vor den übereinstimmenden Zeilen zu drucken, können Sie awk verwenden stattdessen:

 find . -name "*.py" -exec awk " FNR == 1 {filename_printed = 0} /something/ { if (!filename_printed) { print FILENAME filename_printed = 1 } print }" {} +  

Oder rufen Sie grep zweimal für jede Datei – obwohl dies „weniger effizient wäre, da mindestens ein grep -Befehl und bis zu zwei für jede Datei ausgeführt würden (und der Inhalt der Datei zweimal gelesen würde) ):

 find . -name "*.py" -exec grep -l something {} \; \ -exec grep something {} \;  

In jedem Fall Sie möchten die Ausgabe von find nicht so durchlaufen und denken Sie daran, Ihre zu zitieren Variablen .

Wenn Sie eine Shell-Schleife mit GNU-Tools verwenden möchten:

 find . -name "*.py" -exec grep -l --null something {} + | xargs -r0 sh -c " for file do printf "%s\n" "$file" grep something < "$file" done" sh  

(funktioniert auch mit FreeBSD und Derivaten).

Antwort

I. Wenn Sie GNU grep verwenden, können Sie die Option -r oder --recursive verwenden, um diese einfache Suche für Sie durchzuführen:

 grep -r --include "*.py" -le "$regexp" ./ # for filenames only grep -r --include "*.py" -He "$regexp" ./ # for filenames on each match  

Sie benötigen find nur, wenn Sie dies benötigen Fortgeschrittenere Prädikate.

Kommentare

  • Abhängig von der Version von GNU grep, grep kann in Symlinks schauen oder nicht oder Symlinks zu Verzeichnissen durchlaufen. Möglicherweise gibt es auch einige Unterschiede bei der Behandlung anderer Arten von nicht regulären Dateien.

Antwort

Sie kann grep anweisen, den Dateinamen in die Ausgabe aufzunehmen. Wenn also eine Übereinstimmung vorliegt, wird diese auf der Konsole angezeigt. Wenn innerhalb einer Datei keine Übereinstimmung vorliegt, wird für diese Datei keine Zeile gedruckt.

find . -name "*.py" | xargs grep -n -H something 

Aus der man grep:

-H Always print filename headers with output lines -n, --line-number Each output line is preceded by its relative line number in the file, starting at line 1. The line number counter is reset for each file processed. This option is ignored if -c, -L, -l, or -q is specified. 

Wenn Ihre Dateien möglicherweise Namen mit Leerzeichen enthalten, müssen Sie die Pipe wechseln, um NUL-Zeichen als Trennzeichen zu verwenden. Der vollständige Befehl sieht nun folgendermaßen aus:

find . -name "*.py" -print0 | xargs -0 grep -n -H something 

Antwort

Sie können Versuchen Sie Folgendes:

find . -name "*.py:" -exec grep -l {} \; 

Dieser Befehl exec grep für jede Datei, der vom Befehl find und seiner Standardfunktion find command

Antwort

Verwenden Sie das Argument -l.

for file in `find . -name "*.py"`; do grep -l something $file && grep something $file; done 

Eine ausführlichere Verwendung wäre:

for file in $(find . -name "*.py" -exec grep -l something "{}" +); do echo "$file"; grep something $file; done 

Antwort

Dort sind grep Alternativen, die ihre Ergebnisse standardmäßig in dem gewünschten Format ausgeben. Die 2 beliebtesten, die ich kenne, sind ag (a.k.a. „der silberne Sucher“) und ack. ag wird als schnellere Alternative zu ack beworben.

$ ag "^\w+\s*\w+\(" ~/build/i3/src build/i3/src/display_version.c 58:void display_running_version(void) { build/i3/src/load_layout.c 42:static TAILQ_HEAD(focus_mappings_head, focus_mapping) focus_mappings = 518:json_content_t json_determine_content(const char *filename) { 575:void tree_append_json(Con *con, const char *filename, char **errormsg) { build/i3/src/x.c 64:CIRCLEQ_HEAD(state_head, con_state) state_head = 67:CIRCLEQ_HEAD(old_state_head, con_state) old_state_head = 70:TAILQ_HEAD(initial_mapping_head, con_state) initial_mapping_head = 97:void x_con_init(Con *con, uint16_t depth) { ... 

Ich kann es Ihnen hier nicht zeigen, aber die Ausgabe ist ordentlich gefärbt. Ich erhalte die Dateinamen in Olivgrün, die Zeilennummern in Goldgelb und das passende Stück in jeder Zeile in Blutrot. Die Farben sind jedoch anpassbar.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.