Rekursives Suchen von Dateien nach Inhalt

Rekursives Suchen von Dateien nach Inhalt

Ich möchte Dateien in meinem Quellbaum rekursiv nach Inhalt suchen. Ich habe Folgendes mit grep versucht:

$ grep -rn printf | grep %s | grep bcm_errmsg\(rv\)

Dadurch werden mir alle Zeilen zurückgegeben, die ich wollte. Jetzt möchte ich jedoch den Dateinamen aller übereinstimmenden Dateien erhalten und habe ihn daher wie folgt geändert:

$ grep -rn printf | grep %s | grep -l bcm_errmsg\(rv\)

aber anstatt die Dateinamen auszudrucken, bekomme ich nur

(standard input)

auf Standardausgabe gedruckt. Wie behebe ich das, um jeden Dateinamen und Pfad (zur Verwendung sed) zu erhalten?

Was ich tun möchte: Alle Dateien mit printfZeilen suchen, die auch und enthalten %sund bcm_errmsg(rv)dann den folgenden sed-Befehl auf die gefundenen Dateien anwenden:

sed -i 's/%s/%d/g; s/bcm_errmsg(rv)/rv/g;'

Antwort1

fooIch denke, Sie machen die Sache zu kompliziert. Um in allen Dateien im aktuellen Verzeichnis und in den Unterverzeichnissen nach Zeichenfolgen zu suchen , führen Sie einfach Folgendes aus:

grep -r "foo" *

Standardmäßig gibt grep die übereinstimmende Zeile aus, wobei der Dateiname, in dem sie gefunden wurde, vorangestellt wird.

Folgendes gibt stattdessen nur den Dateinamen ohne die entsprechende Zeile aus:

grep -rl "foo" *

Antwort2

Wenn Sie der ursprünglichen Idee von @steeldriver folgen, können Sie Folgendes tun:

egrep -rl '.*printf.*%s.*bcm_errmsg\(rv\).*' . | xargs -d '\n' sed -i '/printf/ s/%s/%d/; /printf/ s/bcm_errmsg(rv)/rv/'

Antwort3

grep -rlZP '(?=.*printf)(?=.*%s)(?=.*bcm_errstr\(rv\))' . |
xargs -r0 sed -i -e '
        /%s/!b
        /printf/!b
        /bcm_errstr(rv)/!b
        s/%s/%d/g;s/bcm_errstr(rv)/rv/g
'

Wir führen zuerst ein rekursives Verzeichnis aus, das nach Dateien sucht, die die Zeichenfolgen printf, %s und bcm_errstr(rv) in derselben Zeile, aber möglicherweise in beliebiger Reihenfolge, enthalten. Die grepOptionen, die uns dabei helfen, sind:

  • -r=> wird rekursiv für alle Dateien im aktuellen Verzeichnis und darunter ausgeführt.
  • -l=> listet Dateinamen auf, die den Kriterien entsprechen, d. h. alle 3 Zeichenfolgen in derselben Zeile.
  • -Z=> die ausgewählten Dateinamen werden durch Nullen (\0) statt durch die übliche neue Zeile (\n) getrennt, sodass wir jede Art von Dateinamen verarbeiten können.
  • -P=> Aktivieren Sie die Perl-Regex-Engine, wodurch wir Lookaheads verwenden können, um zu bestimmen, ob die 3 Zeichenfolgen in derselben Zeile vorhanden sind.

Auf der anderen Seite der Pipe xargswartet es auf den Empfang der durch \0 getrennten Dateinamen. Anschließend werden alle diese Dateinamen, soweit möglich, an die sed-Befehlszeile weitergeleitet. Den sed-Befehl kennen Sie bereits aus Ihrer vorherigen Frage, wo er die Subs nur in den Zeilen ausführt, die die 3 Zeichenfolgen in derselben Zeile enthalten.

verwandte Informationen