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
Verwenden Sie das Argument Eine ausführlichere Verwendung wäre: Dort sind 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. -l
. for file in `find . -name "*.py"`; do grep -l something $file && grep something $file; done
for file in $(find . -name "*.py" -exec grep -l something "{}" +); do echo "$file"; grep something $file; done
Antwort
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) { ...