Ich suche nach der Zeichenfolge foo=
in Textdateien in einem Verzeichnisbaum. Es ist auf einem gängigen Linux-Rechner, ich habe Bash-Shell:
grep -ircl "foo=" *
In den Verzeichnissen befinden sich auch viele Binärdateien, die mit "foo =" übereinstimmen. Da diese Ergebnisse nicht relevant sind und die Suche verlangsamen, möchte ich, dass grep das Durchsuchen dieser Dateien (hauptsächlich JPEG- und PNG-Bilder) überspringt. Wie würde ich das machen?
Ich weiß, dass es die Optionen --exclude=PATTERN
und --include=PATTERN
gibt, aber wie lautet das Musterformat? Die Manpage von grep sagt:
--include=PATTERN Recurse in directories only searching file matching PATTERN.
--exclude=PATTERN Recurse in directories skip file matching PATTERN.
Suche nach grep include, grep include exclude, grep exclude und Varianten haben nichts Relevantes gefunden
Wenn es eine bessere Möglichkeit gibt, nur in bestimmten Dateien zu greifen, bin ich dafür. Das Verschieben der fehlerhaften Dateien ist keine Option. Ich kann nicht nur bestimmte Verzeichnisse durchsuchen (die Verzeichnisstruktur ist ein großes Durcheinander, mit allem überall). Außerdem kann ich nichts installieren, daher habe ich mit gängigen Tools zu tun (wie grep oder dem vorgeschlagenen find).
Verwenden Sie die Shell-Globbing-Syntax:
grep pattern -r --include=\*.{cpp,h} rootdir
Die Syntax für --exclude
ist identisch.
Beachten Sie, dass der Stern mit einem Backslash maskiert wird, um zu verhindern, dass er von der Shell erweitert wird (Anführungszeichen wie --include="*.{cpp,h}"
würden genauso gut funktionieren). Wenn sich im aktuellen Arbeitsverzeichnis Dateien befanden, die dem Muster entsprachen, wurde die Befehlszeile auf grep pattern -r --include=foo.cpp --include=bar.h rootdir
erweitert, wodurch nur die Dateien mit den Namen foo.cpp
und bar.h
durchsucht wurden ist ziemlich wahrscheinlich nicht das, was du wolltest.
Wenn Sie nur Binärdateien überspringen möchten, sollten Sie sich die Option -I
(i in Großbuchstaben) ansehen. Es ignoriert Binärdateien. Ich benutze regelmäßig den folgenden Befehl:
grep -rI --exclude-dir="\.svn" "pattern" *
Es sucht rekursiv, ignoriert Binärdateien und sucht nicht in versteckten Ordnern von Subversion nach einem von mir gewünschten Muster. Ich habe es als "grepsvn" auf meiner Box bei der Arbeit aliasiert.
Schauen Sie sich bitte ack an, das genau für diese Situationen ausgelegt ist. Ihr Beispiel von
grep -ircl --exclude=*.{png,jpg} "foo=" *
wird mit ack als erledigt
ack -icl "foo="
weil ack standardmäßig nie in binären Dateien sucht und -r standardmäßig aktiviert ist. Und wenn Sie nur CPP- und H-Dateien möchten, tun Sie dies einfach
ack -icl --cpp "foo="
Ich habe nach langer Zeit festgestellt, dass Sie mehrere Einschlüsse und Ausschlüsse hinzufügen können, wie zum Beispiel:
grep "z-index" . --include=*.js --exclude=*js/lib/* --exclude=*.min.js
Der vorgeschlagene Befehl:
grep -Ir --exclude="*\.svn*" "pattern" *
ist konzeptionell falsch, da --exclude mit dem Basisnamen arbeitet. Mit anderen Worten, es wird nur die .svn im aktuellen Verzeichnis übersprungen.
In grep 2.5.1 müssen Sie diese Zeile zum Profil ~/.bashrc oder ~/.bash hinzufügen
export GREP_OPTIONS="--exclude=\*.svn\*"
Ich finde, dass die Ausgabe von grep manchmal sehr hilfreich ist:
grep -rn "foo=" . | grep -v "Binary file"
Das hindert es jedoch nicht daran, die Binärdateien zu durchsuchen.
Unter CentOS 6.6/Grep 2.6.3 muss ich es folgendermaßen verwenden:
grep "term" -Hnir --include \*.php --exclude-dir "*excluded_dir*"
Beachten Sie das Fehlen von Gleichheitszeichen "=" (andernfalls werden --include
, --exclude
, include-dir
und --exclude-dir
ignoriert)
Wenn Sie die Verwendung von find
nicht ablehnen, gefällt mir die Funktion -Prune
:
find [directory] \
-name "pattern_to_exclude" -Prune \
-o -name "another_pattern_to_exclude" -Prune \
-o -name "pattern_to_INCLUDE" -print0 \
| xargs -0 -I FILENAME grep -IR "pattern" FILENAME
In der ersten Zeile geben Sie das Verzeichnis an, in dem Sie suchen möchten. .
(aktuelles Verzeichnis) ist beispielsweise ein gültiger Pfad.
Verwenden Sie in der 2. und 3. Zeile "*.png"
, "*.gif"
, "*.jpg"
und so weiter. Verwenden Sie so viele dieser -o -name "..." -Prune
-Konstrukte, wie Sie Muster haben.
In der vierten Zeile benötigen Sie einen anderen -o
(der "oder" für find
angibt), die gewünschten Muster und am Ende einen -print
oder -print0
. Wenn Sie nur "alles andere" möchten, das nach dem Beschneiden der Bilder *.gif
, *.png
usw. verbleibt, verwenden Sie -o -print0
, und Sie sind mit der 4. Zeile fertig.
Schließlich befindet sich in der 5. Zeile die Pipe zu xargs
, die jede dieser resultierenden Dateien aufnimmt und in einer Variablen FILENAME
speichert. Anschließend werden grep
die Flags -IR
und "pattern"
übergeben, und dann wird FILENAME
um xargs
erweitert, um die Liste der von find
gefundenen Dateinamen zu werden.
Für Ihre spezielle Frage könnte die Aussage ungefähr so aussehen:
find . \
-name "*.png" -Prune \
-o -name "*.gif" -Prune \
-o -name "*.svn" -Prune \
-o -print0 | xargs -0 -I FILES grep -IR "foo=" FILES
Ich bin ein Dilettant, aber so sieht mein ~/.bash_profile aus:
export GREP_OPTIONS = "- orl --exclude-dir = .svn --exclude-dir = .cache --color = auto" GREP_COLOR = '1; 32'
Beachten Sie, dass ich --exclude-dir zweimal verwenden musste, um zwei Verzeichnisse auszuschließen.
git grep
Verwenden Sie _git grep
_, das für die Leistung optimiert ist und darauf abzielt, bestimmte Dateien zu durchsuchen.
Standardmäßig werden Binärdateien ignoriert und Ihr _.gitignore
_ wird gewürdigt. Wenn Sie nicht mit der Git-Struktur arbeiten, können Sie sie trotzdem verwenden, indem Sie _--no-index
_ übergeben.
Beispielsyntax:
_git grep --no-index "some_pattern"
_
Weitere Beispiele finden Sie unter:
Probier diese:
$ find. -name "* .txt" -Typ f -print | xargs datei | grep "foo =" | cut -d: -f1
Hier gefunden: http://www.unix.com/Shell-programming-scripting/42573-search-files-excluding-binary-files.html
Wenn Sie nicht rekursiv suchen, können Sie Glop-Muster verwenden, um die Dateinamen abzugleichen.
grep "foo" *.{html,txt}
beinhaltet HTML und TXT. Es wird nur im aktuellen Verzeichnis gesucht.
So suchen Sie in den Unterverzeichnissen:
grep "foo" */*.{html,txt}
In den Unterverzeichnissen:
grep "foo" */*/*.{html,txt}
Schauen Sie sich diesen an.
grep --exclude="*\.svn*" -rn "foo=" * | grep -v Binary | grep -v tags
diese Skripte lösen nicht alle Probleme ... Versuchen Sie es besser:
du -ha | grep -i -o "\./.*" | grep -v "\.svn\|another_file\|another_folder" | xargs grep -i -n "$1"
dieses Skript ist so besser, weil es "echte" reguläre Ausdrücke verwendet, um zu vermeiden, dass Verzeichnisse durchsucht werden. Trennen Sie einfach die Ordner- oder Dateinamen mit "\ |" auf dem grep -v
geniesse es! auf meiner Linux-Shell gefunden! XD
In den Verzeichnissen befinden sich auch viele Binärdateien. Ich kann nicht nur bestimmte Verzeichnisse durchsuchen (die Verzeichnisstruktur ist ein großes Durcheinander). Gibt es eine bessere Möglichkeit, nur in bestimmten Dateien zu greifen?
ripgrep
Dies ist eines der schnellsten Tools, mit denen Sie Ihr aktuelles Verzeichnis rekursiv durchsuchen können. Es ist geschrieben in Rust , gebaut auf Rusts Regex-Engine für maximale Effizienz. Überprüfen Sie die detaillierte Analyse hier .
So können Sie einfach laufen:
rg "some_pattern"
Es respektiert Ihren .gitignore
und überspringt automatisch versteckte Dateien/Verzeichnisse und Binärdateien.
Sie können weiterhin Dateien und Verzeichnisse mit -g
/--glob
ein- oder ausschließen. Globbing-Regeln stimmen mit .gitignore
Globs überein. Überprüfen Sie man rg
auf Hilfe.
Weitere Beispiele finden Sie unter: So schließen Sie einige Dateien aus, die bestimmten Erweiterungen mit grep nicht entsprechen?
Unter macOS können Sie über brew install ripgrep
installieren.
find und xargs sind deine Freunde. Verwenden Sie sie, um die Dateiliste zu filtern, anstatt das --exclude von grep
Versuchen Sie etwas wie
find . -not -name '*.png' -o -type f -print | xargs grep -icl "foo="
geeignet für tcsh .alias datei:
alias gisrc 'grep -I -r -i --exclude="*\.svn*" --include="*\."{mm,m,h,cc,c} \!* *'
Ich habe eine Weile gebraucht, um herauszufinden, dass der Teil {mm, m, h, cc, c} NICHT in Anführungszeichen stehen sollte. ~ Keith
Mit der Option --binary-files=without-match
zu GNU grep
werden Binärdateien übersprungen. (Entspricht dem an anderer Stelle erwähnten Schalter -I
.)
(Dies erfordert möglicherweise eine neuere Version von grep
; mindestens 2.5.3.)
Um alle binären Ergebnisse von grep zu ignorieren
grep -Ri "pattern" * | awk '{if($1 != "Binary") print $0}'
Der awk-Teil filtert alle Binärdateien für Übereinstimmungen heraus