Ich benutze den find
Befehl oft, um den Quellcode zu durchsuchen, Dateien zu löschen, was auch immer. Ärgerlicherweise, weil Subversion Duplikate jeder Datei in seinen .svn/text-base/
Verzeichnissen speichert, erhalten meine einfachen Suchvorgänge viele doppelte Ergebnisse. Zum Beispiel möchte ich rekursiv uint
in mehreren messages.h
und messages.cpp
Dateien suchen :
# find -name 'messages.*' -exec grep -Iw uint {} +
./messages.cpp: Log::verbose << "Discarding out of date message: id " << uint(olderMessage.id)
./messages.cpp: Log::verbose << "Added to send queue: " << *message << ": id " << uint(preparedMessage->id)
./messages.cpp: Log::error << "Received message with invalid SHA-1 hash: id " << uint(incomingMessage.id)
./messages.cpp: Log::verbose << "Received " << *message << ": id " << uint(incomingMessage.id)
./messages.cpp: Log::verbose << "Sent message: id " << uint(preparedMessage->id)
./messages.cpp: Log::verbose << "Discarding unsent message: id " << uint(preparedMessage->id)
./messages.cpp: for (uint i = 0; i < 10 && !_stopThreads; ++i) {
./.svn/text-base/messages.cpp.svn-base: Log::verbose << "Discarding out of date message: id " << uint(olderMessage.id)
./.svn/text-base/messages.cpp.svn-base: Log::verbose << "Added to send queue: " << *message << ": id " << uint(preparedMessage->id)
./.svn/text-base/messages.cpp.svn-base: Log::error << "Received message with invalid SHA-1 hash: id " << uint(incomingMessage.id)
./.svn/text-base/messages.cpp.svn-base: Log::verbose << "Received " << *message << ": id " << uint(incomingMessage.id)
./.svn/text-base/messages.cpp.svn-base: Log::verbose << "Sent message: id " << uint(preparedMessage->id)
./.svn/text-base/messages.cpp.svn-base: Log::verbose << "Discarding unsent message: id " << uint(preparedMessage->id)
./.svn/text-base/messages.cpp.svn-base: for (uint i = 0; i < 10 && !_stopThreads; ++i) {
./virus/messages.cpp:void VsMessageProcessor::_progress(const string &fileName, uint scanCount)
./virus/messages.cpp:ProgressMessage::ProgressMessage(const string &fileName, uint scanCount)
./virus/messages.h: void _progress(const std::string &fileName, uint scanCount);
./virus/messages.h: ProgressMessage(const std::string &fileName, uint scanCount);
./virus/messages.h: uint _scanCount;
./virus/.svn/text-base/messages.cpp.svn-base:void VsMessageProcessor::_progress(const string &fileName, uint scanCount)
./virus/.svn/text-base/messages.cpp.svn-base:ProgressMessage::ProgressMessage(const string &fileName, uint scanCount)
./virus/.svn/text-base/messages.h.svn-base: void _progress(const std::string &fileName, uint scanCount);
./virus/.svn/text-base/messages.h.svn-base: ProgressMessage(const std::string &fileName, uint scanCount);
./virus/.svn/text-base/messages.h.svn-base: uint _scanCount;
Wie kann ich sagen find
, dass die .svn
Verzeichnisse ignoriert werden sollen ?
Update : Wenn Sie Ihren SVN-Client auf Version 1.7 aktualisieren, ist dies kein Problem mehr.
Ein wesentliches Merkmal der in Subversion 1.7 eingeführten Änderungen ist die Zentralisierung des Speichers von Arbeitskopien-Metadaten an einem einzigen Speicherort. Anstelle eines
.svn
Verzeichnisses in jedem Verzeichnis in der Arbeitskopie haben Subversion 1.7-Arbeitskopien nur ein.svn
Verzeichnis - im Stammverzeichnis der Arbeitskopie. Dieses Verzeichnis enthält (unter anderem) eine SQLite-gestützte Datenbank, die alle Metadaten enthält, die Subversion für diese Arbeitskopie benötigt.
find ... -print0 | xargs -0 egrep ...
anstelle von zu verwendenfind ... -exec grep ...
(nichtgrep
für jede Datei, sondern für mehrere Dateien gleichzeitig). Mit diesem Formular können Sie auch.svn
Verzeichnisse-prune
find ... -print0 | egrep -v '/\.svn' | xargs -0 egrep ...
-exec
mit+
Gabel nichtgrep
für jede Datei, während es bei der Verwendung des;
Fall ist. Verwenden-exec
ist eigentlich korrekter als Verwendenxargs
. Bitte beachten Sie, dass Befehle wie "ls
etwas tun", auch wenn die Argumentliste leer ist, während Befehle wie "chmod
Fehler" geben, wenn nicht genügend Argumente vorhanden sind. Um zu sehen, was ich meine, versuchen Sie einfach den folgenden Befehl in einem Verzeichnis, das kein Shell-Skript enthält :find /path/to/dir -name '*.sh' -print0 | xargs -0 chmod 755
. Vergleichen Sie mit diesem :find /path/to/dir -name '*.sh' -exec chmod 755 '{}' '+'
.grep
-ing out.svn
ist auch keine gute Idee. Währendfind
es auf die Behandlung von Dateieigenschaften spezialisiert ist, istgrep
dies nicht der Fall. In Ihrem Beispiel wird eine Datei mit dem Namen '.svn.txt' ebenfalls von Ihremegrep
Befehl gefiltert . Obwohl Sie Ihren regulären Ausdruck in '^ / \. Svn $' ändern können , ist dies immer noch keine gute Vorgehensweise. Das-prune
Prädikat vonfind
eignet sich perfekt zum Filtern einer Datei (nach Dateiname, Erstellungszeitstempel oder der von Ihnen angegebenen Bedingung). Es ist so, als ob selbst wenn man eine Kakerlake mit einem großen Schwert töten kann, dies nicht bedeutet, dass dies der vorgeschlagene Weg ist :-).Antworten:
Kann ich Ihnen für die Suche vorschlagen, sich ack anzuschauen ? Es ist ein Quellcode-fähig
find
und ignoriert daher automatisch viele Dateitypen, einschließlich Quellcode-Repository-Informationen wie die oben genannten.quelle
ack
sehr, aber ich habe festgestellt, dass es wesentlich langsamer ist alsfind -type f -name "*.[ch]" | xargs grep
beim Umgang mit einer großen Codebasis.ack
als bessergrep
, nicht quellenbewusst abgerechnetfind
? Einige Beispiele für die Verwendung als Ersatzfind
würden dies zu einer echten Antwort machen.warum nicht einfach
Das Prädikat -not negiert alles, was irgendwo im Pfad .svn hat.
In Ihrem Fall wäre es also so
quelle
'*.svn*'
zuerst aber dann gesagt'*.svn'
. Welches ist richtig? Arbeiten beide? Ich denke es sollte wohl sein'*.svn*'
?Wie folgt:
Oder alternativ basierend auf einem Verzeichnis und nicht auf einem Pfadpräfix:
quelle
find . -type d -name .svn -prune -o -print
weil es etwas schneller ist. Gemäß dem POSIX-Standard werden die Ausdrücke einzeln in der angegebenen Reihenfolge ausgewertet. Wenn der erste Ausdruck in-a
istfalse
, wird der zweite Ausdruck nicht ausgewertet (auch Kurzschluss und Auswertung genannt ).-type d
bevor-name .svn
theoretisch effizienter. Es ist jedoch normalerweise unbedeutend, außer wenn Sie einen sehr sehr großen Verzeichnisbaum haben.-print
als Teil des letzten Ausdrucks. So etwasfind . -name .git -prune -o \( -type f -name LICENSE -print \)
funktioniert wie erwartet.find . -name .svn -prune -o -name .git -prune -o -type d -print
. Es mag ein paar Millisekunden schneller sein,-type d
vor die beiden zu-name
treten, aber die zusätzliche Eingabe lohnt sich nicht.Versuchen Sie Folgendes
.svn
, um.git
andere versteckte Verzeichnisse (beginnend mit einem Punkt) zu ignorieren :Wenn der Verwendungszweck jedoch darin
find
besteht, in den Dateien zu suchen, können Sie versuchen, die folgenden Befehle zu verwenden:git grep
- Speziell entwickelter Befehl zum Suchen von Mustern im Git-Repository.ripgrep
- die standardmäßig versteckte Dateien und Dateien ignoriert, die in angegeben sind.gitignore
.Verwandte: Wie finde ich alle Dateien, die bestimmten Text enthalten, unter Linux?
quelle
Folgendes würde ich in Ihrem Fall tun:
Der in Emacs
rgrep
integrierte Befehl ignoriert das.svn
Verzeichnis und viele weitere Dateien, an denen Sie wahrscheinlich nicht interessiert sind, wenn Sie eine ausführenfind | grep
. Folgendes wird standardmäßig verwendet:Verzeichnisse, die von den meisten Versionskontrollsystemen erstellt wurden, sowie generierte Dateien für viele Programmiersprachen werden ignoriert. Sie können einen Alias erstellen, der diesen Befehl aufruft
find
undgrep
Muster für Ihre spezifischen Probleme ersetzt.quelle
GNU finden
quelle
-type d
) nicht herausgefiltert - diese Antwort hat es getan. +1Ich benutze grep für diesen Zweck. Tragen Sie dies in Ihr ~ / .bashrc ein
grep verwendet diese Optionen beim Aufruf automatisch
quelle
GREP_OPTIONS=xxx grep "$@"
. Dies bedeutet, dass die Variable GREP_OPTIONS nur für Instanzen von grep festgelegt ist, die ich manuell mit 'grp' ausführe. Dies bedeutet, dass ich nie eine Situation bekomme, in der ich ein Tool ausführe, und intern ruft es grep auf, aber das Tool wird verwirrt, weil grep sich nicht wie erwartet verhält. Außerdem habe ich eine zweite Funktion 'grpy', die 'grp' aufruft, aber hinzufügt--include=*.py
, um nur Python-Dateien zu durchsuchen.grep --exclude=tags --exclude_dir=.git ...etc... "$@"
. Ich mag es, dass dies wie "ack" läuft, aber ich behalte das Bewusstsein und die Kontrolle darüber, was es tut.find . | grep -v \.svn
quelle
.
im.svn
regulären Ausdruck entkommen .| fgrep -v /.svn/
oder `| grep -F -v / .svn / `, um genau das Verzeichnis auszuschließen und keine Dateien mit" .svn "als Teil ihres Namens.Warum leiten Sie Ihren Befehl nicht mit grep weiter, was leicht verständlich ist:
quelle
.
im.svn
regulären Ausdruck entkommen .Erstellen Sie ein Skript mit dem Namen
~/bin/svnfind
:Dieses Skript verhält sich identisch mit einem einfachen
find
Befehl, wird jedoch entfernt.svn
Verzeichnisse. Ansonsten ist das Verhalten identisch.Beispiel:
quelle
echo
dem Befehl find ein hinzufügen und mir sagen, welcher Befehl ausgeführt wird?svnfind -type f
funktioniert hervorragend auf meinem Red Hat-Computer.echo find "${OPTIONS[@]}"...
damit der Befehl find gedruckt wird, anstatt ihn tatsächlich auszuführen .echo find ${OPTIONS[@]} ${PATHS[@]} -name .svn -type d -prune -o ( ${EXPR[@]} ) $ACTION
, Dies gibt mir die folgende Ausgabe:find -type f -name .svn -type d -prune -o ( -true ) -print
Ich dachte , ich hinzufügen würde eine einfache Alternative zu Kaleb ist und Beiträge anderer (die die Verwendung der detaillierten
find -prune
Optionack
,repofind
Befehle usw.), die auf die Verwendung besonders für Sie in der Frage beschriebenen (und jede andere ähnliche Verwendungen):Für die Leistung sollten Sie immer versuchen,
find ... -exec grep ... +
(danke Kenji für den Hinweis) oderfind ... | xargs egrep ...
(portabel) oderfind ... -print0 | xargs -0 egrep ...
(GNU; arbeitet mit Dateinamen, die Leerzeichen enthalten) anstelle von zu verwendenfind ... -exec grep ... \;
.Das
find ... -exec ... +
undfind | xargs
-Formular teilt sich nichtegrep
für jede Datei, sondern für eine Reihe von Dateien gleichzeitig, was zu einer viel schnelleren Ausführung führt .Bei Verwendung des
find | xargs
Formulars können Sie auch verwenden ,grep
um einfach und schnell Pflaume.svn
(oder alle Verzeichnisse oder ein regulärer Ausdruck), dhfind ... -print0 | grep -v '/\.svn' | xargs -0 egrep ...
(nützlich , wenn Sie etwas schnell brauchen , und nicht gestört werden können , um daran erinnern , wie einzurichtenfind
‚s-prune
Logik.)Der
find | grep | xargs
Ansatz ähnelt GNUfind
‚s --regex
Option (sieheghostdog74
‘ s post), ist aber mehr tragbar (funktioniert auch auf Plattformen , auf denen GNUfind
ist nicht verfügbar.)quelle
-exec
Wechsel gibtfind
: eine endet mit;
und die andere endet mit+
. Der eine mit der Endung+
ersetzt{}
durch eine Liste aller passenden Dateien. Außerdem'/\.svn'
stimmt Ihre Regex auch mit Dateinamen überein'.svn.txt'
. Weitere Informationen finden Sie in meinen Kommentaren zur Frage.find
Dienstprogramm. Bitte beachten Sie den-exec
Teil :-).In einem Quellcode-Repository möchte ich im Allgemeinen nur die Textdateien bearbeiten.
Die erste Zeile enthält alle Dateien mit Ausnahme der CVS-, SVN- und GIT-Repository-Dateien.
Die zweite Zeile schließt alle Binärdateien aus.
quelle
Ich benutze find mit den Optionen -not -path. Ich hatte kein Glück mit Pflaumen.
findet die groovigen Dateien nicht im Zielverzeichnispfad.
quelle
Um dieses Problem zu beheben, können Sie einfach diese Suchbedingung verwenden:
Sie können weitere Einschränkungen wie folgt hinzufügen:
Weitere Informationen hierzu finden Sie im Manpage-Abschnitt "Operatoren": http://unixhelp.ed.ac.uk/CGI/man-cgi?find
quelle
Beachten Sie dies, wenn Sie dies tun
find . -type f -name 'messages.*'
dann
-print
wird impliziert, wenn der gesamte Ausdruck (-type f -name 'messages.*'
) wahr ist, weil es keine 'Aktion' (wie-exec
) gibt.Um den Abstieg in bestimmte Verzeichnisse zu beenden, sollten Sie alles verwenden, was mit diesen Verzeichnissen übereinstimmt, und ihm folgen
-prune
(was den Abstieg in Verzeichnisse beenden soll). wie so:find . -type d -name '.svn' -prune
Dies wird für die .svn-Verzeichnisse als True ausgewertet , und wir können einen booleschen Kurzschluss verwenden, indem wir diesem durch
-o
(OR) folgen. Danach wird das, was nach dem-o
folgt, nur überprüft, wenn der erste Teil False ist, und ist daher kein .svn-Verzeichnis. Mit anderen Worten:find . -type d -name '.svn' -prune -o -name 'message.*' -exec grep -Iw uint {}
wird nur bewerten, was richtig ist
-o
, nämlich-name 'message.*' -exec grep -Iw uint {}
für Dateien, die sich NICHT in .svn-Verzeichnissen befinden.Beachten Sie, dass Sie, da
.svn
es sich wahrscheinlich immer um ein Verzeichnis handelt (und nicht zum Beispiel um eine Datei) und in diesem Fall sicherlich nicht mit dem Namen 'message. *' Übereinstimmt, das-type d
und auch tun können:find . -name '.svn' -prune -o -name 'message.*' -exec grep -Iw uint {}
Beachten Sie schließlich, dass Sie, wenn Sie eine Aktion auslassen (
-exec
eine Aktion ist), wie folgt sagen:find . -name '.svn' -prune -o -name 'message.*'
Dann wird die
-print
Aktion impliziert, gilt jedoch für den GANZEN Ausdruck, einschließlich des-name '.svn' -prune -o
Teils, und druckt somit alle .svn-Verzeichnisse sowie die 'message. *' - Dateien, was wahrscheinlich nicht das ist, was Sie wollen. Daher sollten Sie auf diese Weise immer eine 'Aktion' auf der rechten Seite des booleschen Ausdrucks verwenden-prune
. Und wenn diese Aktion gedruckt wird, müssen Sie sie explizit hinzufügen, wie folgt:find . -name '.svn' -prune -o -name 'message.*' -print
quelle
Versuchen Sie es mit findrepo , einem einfachen Wrapper um find / grep und viel schneller als ack. Sie würden es in diesem Fall wie folgt verwenden:
quelle
wcfind
ist ein Find-Wrapper-Skript, mit dem ich .svn-Verzeichnisse automatisch entferne.quelle
Dies funktioniert bei mir in der Unix-Eingabeaufforderung
Mit dem obigen Befehl werden DATEIEN aufgelistet, die nicht mit .svn verknüpft sind, und der von Ihnen erwähnte grep ausgeführt.
quelle
xxx.svnxxx
. Dies ist wichtig. Wenn Sie beispielsweise git anstelle von svn verwenden, möchten Sie häufig Dateien wie .gitignore (keine Metadaten, sondern eine reguläre Datei, die im Repo enthalten ist) in die Ergebnisse von find aufnehmen.Normalerweise leite ich die Ausgabe noch einmal durch grep und entferne .svn. Bei meiner Verwendung ist sie nicht viel langsamer. typisches Beispiel:
ODER
quelle