it-swarm.com.de

Wie kann ich finden, um .svn-Verzeichnisse zu ignorieren?

Ich verwende oft den Befehl find, um den Quellcode zu durchsuchen, Dateien zu löschen, was auch immer. Da Subversion Duplikate jeder Datei in ihren .svn/text-base/ - Verzeichnissen speichert, führen meine einfachen Suchanfragen zu vielen doppelten Ergebnissen. Ich möchte beispielsweise rekursiv nach 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 find anweisen, die Verzeichnisse .svn Zu ignorieren?


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 Metadatenspeichers der Arbeitskopie an einem einzigen Speicherort. Anstelle eines .svn - Verzeichnisses in jedem Verzeichnis 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.

219
John Kugelman

Kann ich für die Suche vorschlagen, dass Sie sich ack ansehen? Es ist ein Quellcode-fähiger find und ignoriert daher automatisch viele Dateitypen, einschließlich Informationen zum Quellcode-Repository wie oben.

64
Brian Agnew

warum nicht einfach

find . -not -iwholename '*.svn*'

Das -not-Prädikat negiert alles, was .svn irgendwo im Pfad hat.

So wäre es in deinem Fall

find -not -iwholename '*.svn*' -name 'messages.*' -exec grep -Iw uint {} + \;
287
whaley

Wie folgt:

find . -path '*/.svn*' -Prune -o -print

Oder alternativ basierend auf einem Verzeichnis und nicht einem Pfadpräfix:

find . -name .svn -a -type d -Prune -o -print
140
Kaleb Pederson

Um .svn, .git Und andere versteckte Verzeichnisse (beginnend mit einem Punkt) zu ignorieren, versuchen Sie Folgendes:

find . -type f -not -path '*/\.*'

Wenn der Zweck der Verwendung von find darin besteht, in den Dateien zu suchen, können Sie versuchen, die folgenden Befehle zu verwenden:

  • git grep - speziell entwickelter Befehl zum Durchsuchen von Mustern im Git-Repository.
  • ripgrep - ignoriert standardmäßig versteckte Dateien und Dateien, die in .gitignore angegeben sind.

Related: Wie finde ich alle Dateien, die bestimmten Text enthalten, unter Linux?

31
kenorb

Folgendes würde ich in Ihrem Fall tun:

find . -path .svn -Prune -o -name messages.* -exec grep -Iw uint {} +

Der in Emacs integrierte Befehl rgrep ignoriert .svn -Verzeichnis und viele weitere Dateien, an denen Sie wahrscheinlich nicht interessiert sind, wenn Sie ein find | grep. Folgendes wird standardmäßig verwendet:

find . \( -path \*/SCCS -o -path \*/RCS -o -path \*/CVS -o -path \*/MCVS \
          -o -path \*/.svn -o -path \*/.git -o -path \*/.hg -o -path \*/.bzr \
          -o -path \*/_MTN -o -path \*/_darcs -o -path \*/\{Arch\} \) \
     -Prune -o \
       \( -name .\#\* -o -name \*.o -o -name \*\~ -o -name \*.bin -o -name \*.lbin \
          -o -name \*.so -o -name \*.a -o -name \*.ln -o -name \*.blg \
          -o -name \*.bbl -o -name \*.elc -o -name \*.lof -o -name \*.glo \
          -o -name \*.idx -o -name \*.lot -o -name \*.fmt -o -name \*.tfm \
          -o -name \*.class -o -name \*.fas -o -name \*.lib -o -name \*.mem \
          -o -name \*.x86f -o -name \*.sparcf -o -name \*.fasl -o -name \*.ufsl \
          -o -name \*.fsl -o -name \*.dxl -o -name \*.pfsl -o -name \*.dfsl \
          -o -name \*.p64fsl -o -name \*.d64fsl -o -name \*.dx64fsl -o -name \*.lo \
          -o -name \*.la -o -name \*.gmo -o -name \*.mo -o -name \*.toc \
          -o -name \*.aux -o -name \*.cp -o -name \*.fn -o -name \*.ky \
          -o -name \*.pg -o -name \*.tp -o -name \*.vr -o -name \*.cps \
          -o -name \*.fns -o -name \*.kys -o -name \*.pgs -o -name \*.tps \
          -o -name \*.vrs -o -name \*.pyc -o -name \*.pyo \) \
     -Prune -o \
     -type f \( -name pattern \) -print0 \
     | xargs -0 -e grep -i -nH -e regex

Es ignoriert Verzeichnisse, die von den meisten Versionskontrollsystemen erstellt wurden, sowie generierte Dateien für viele Programmiersprachen. Sie können einen Alias ​​erstellen, der diesen Befehl aufruft, und find und grep Muster für Ihre spezifischen Probleme ersetzen.

18
Antoine

GNU finden

find .  ! -regex ".*[/]\.svn[/]?.*"
12
ghostdog74

Ich benutze grep für diesen Zweck. Fügen Sie dies in Ihre ~/.bashrc ein

export GREP_OPTIONS="--binary-files=without-match --color=auto --devices=skip --exclude-dir=CVS --exclude-dir=.libs --exclude-dir=.deps --exclude-dir=.svn"

grep verwendet diese Optionen beim Aufruf automatisch

10
Ronny Brendel

find . | grep -v \.svn

8
me.

Erstelle ein Skript namens ~/bin/svnfind:

#!/bin/bash
#
# Attempts to behave identically to a plain `find' command while ignoring .svn/
# directories.

OPTIONS=()
PATHS=()
EXPR=()

while [[ $1 =~ ^-[HLP]+ ]]; do
    OPTIONS+=("$1")
    shift
done

while [[ $# -gt 0 ]] && ! [[ $1 =~ '^[-(),!]' ]]; do
    PATHS+=("$1")
    shift
done

# If user's expression contains no action then we'll add the normally-implied
# `-print'.
ACTION=-print

while [[ $# -gt 0 ]]; do
    case "$1" in
       -delete|-exec|-execdir|-fls|-fprint|-fprint0|-fprintf|-ok|-print|-okdir|-print0|-printf|-Prune|-quit|-ls)
            ACTION=;;
    esac

    EXPR+=("$1")
    shift
done

if [[ ${#EXPR} -eq 0 ]]; then
    EXPR=(-true)
fi

exec -a "$(basename "$0")" find "${OPTIONS[@]}" "${PATHS[@]}" -name .svn -type d -Prune -o '(' "${EXPR[@]}" ')' $ACTION

Dieses Skript verhält sich identisch zu einem einfachen find Befehl, aber es entfernt .svn Verzeichnisse. Ansonsten ist das Verhalten identisch.

Beispiel:

# svnfind -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) {
./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;
8
John Kugelman

Warum leiten Sie Ihren Befehl nicht mit grep weiter, was leicht zu verstehen ist:

your find command| grep -v '\.svn'
7
Vijay

Ich dachte nur, ich füge eine einfache Alternative zu Kalebs und anderen Posts hinzu (in denen die Verwendung der Option find -Prune, ack, repofind beschrieben wird. Befehle usw.), die insbesondere anwendbar auf die Verwendung, die Sie in der Frage beschrieben haben (und alle anderen ähnlichen Verwendungen):

  1. Für die Leistung sollten Sie immer versuchen, find ... -exec grep ... + (Danke Kenji für den Hinweis) oder find ... | xargs egrep ... (Portabel) oder find ... -print0 | xargs -0 egrep ... (GNU; arbeitet mit Dateinamen, die Leerzeichen enthalten) zu verwenden anstelle von find ... -exec grep ... \;.

    Das Formular find ... -exec ... + Und find | xargs Gibt nicht egrep für jede Datei, sondern für mehrere Dateien gleichzeitig aus, was zu viel schnellerer Ausführung führt =.

  2. Wenn Sie das Formular find | xargs Verwenden, können Sie auch grep verwenden, um einfach und schnell .svn (Oder beliebige Verzeichnisse oder reguläre Ausdrücke) zu bereinigen, dh find ... -print0 | grep -v '/\.svn' | xargs -0 egrep ... (Nützlich, wenn Sie brauchen etwas Schnelles und müssen sich nicht mehr daran erinnern, wie Sie die Logik von find-Prune einrichten.)

    Der Ansatz find | grep | xargs Ähnelt der Option -regex Von GNU find (siehe Beitrag von ghostdog74), Ist aber mehr portabel (funktioniert auch auf Plattformen, auf denen GNU find nicht verfügbar ist.)

5
vladr

In einem Quellcode-Repository möchte ich normalerweise nur die Textdateien bearbeiten.

Die erste Zeile enthält alle Dateien, ausgenommen CVS-, SVN- und GIT-Repository-Dateien.

Die zweite Zeile schließt alle Binärdateien aus.

find . -not \( -name .svn -Prune -o -name .git -Prune -o -name CVS -Prune \) -type f -print0 | \
xargs -0 file -n | grep -v binary | cut -d ":" -f1
4
rickfoosusa

Ich benutze find mit den Optionen -not -path. Ich hatte kein Glück mit Prune.

find .  -name "*.groovy" -not -path "./target/*" -print

findet die groovigen Dateien nicht im Zielverzeichnispfad.

3
scott m gardner

Beachten Sie dies, wenn Sie dies tun

find . -type f -name 'messages.*'

dann ist -print impliziert, wenn der gesamte Ausdruck (-type f -name 'messages.*') wahr ist, weil es keine 'Aktion' gibt (wie -exec).

Um den Abstieg in bestimmte Verzeichnisse zu stoppen, sollten Sie jedoch alle Elemente verwenden, die mit diesen Verzeichnissen übereinstimmen, und danach -Prune (Das den Abstieg in Verzeichnisse stoppen soll) eingeben. wie so:

find . -type d -name '.svn' -Prune

Dies ergibt True für die .svn-Verzeichnisse, und wir können einen booleschen Kurzschluss verwenden, indem wir diesem mit -o (OR) folgen. Danach folgt das, was nach dem -o wird nur geprüft, wenn der erste Teil False ist, daher nicht ein .svn-Verzeichnis. Mit anderen Worten:

find . -type d -name '.svn' -Prune -o -name 'message.*' -exec grep -Iw uint {}

wertet nur das aus, was für Dateien, die sich NICHT in .svn-Verzeichnissen befinden, für das Recht von -o, nämlich -name 'message.*' -exec grep -Iw uint {}, gilt.

Beachten Sie, dass .svn Wahrscheinlich immer ein Verzeichnis ist (und nicht zum Beispiel eine Datei) und in diesem Fall sicherlich nicht mit dem Namen 'message. *' Übereinstimmt. Sie können auch das -type d Und mache:

find . -name '.svn' -Prune -o -name 'message.*' -exec grep -Iw uint {}

Beachten Sie zum Schluss, dass Sie, wenn Sie eine Aktion auslassen (-exec Ist eine Aktion), wie folgt sagen:

find . -name '.svn' -Prune -o -name 'message.*'

dann wird die Aktion -print impliziert, aber auf den GANZEN Ausdruck angewendet, einschließlich des Teils -name '.svn' -Prune -o, und damit werden alle .svn-Verzeichnisse sowie die 'message. *' - Dateien gedruckt, was wahrscheinlich nicht der Fall ist was du willst. Daher sollten Sie bei dieser Verwendung von -Prune Immer eine 'Aktion' auf der rechten Seite des Booleschen Ausdrucks verwenden. Und wenn diese Aktion gedruckt wird, müssen Sie sie explizit wie folgt hinzufügen:

find . -name '.svn' -Prune -o -name 'message.*' -print

2
Carlo Wood

Um dieses Problem zu beheben, können Sie einfach diese Suchbedingung verwenden:

find \( -name 'messages.*' ! -path "*/.svn/*" \) -exec grep -Iw uint {} +

Sie können weitere Einschränkungen wie diese hinzufügen:

find \( -name 'messages.*' ! -path "*/.svn/*" ! -path "*/CVS/*" \) -exec grep -Iw uint {} +

Weitere Informationen hierzu finden Sie im Manpage-Abschnitt "Operatoren": http://unixhelp.ed.ac.uk/CGI/man-cgi?find

2
Code-Source

wcfind ist ein Find Wrapper-Skript, mit dem ich automatisch .svn-Verzeichnisse entferne.

2
leedm777

Versuchen Sie findrepo das ist ein einfacher Wrapper um find/grep und viel schneller als ack. Sie würden ihn in diesem Fall wie folgt verwenden:

findrepo uint 'messages.*'
2
pixelbeat

normalerweise leite ich die Ausgabe ein weiteres Mal durch grep und entferne .svn. In meinem Fall ist es nicht viel langsamer. typisches Beispiel:

find -name 'messages.*' -exec grep -Iw uint {} + | grep -Ev '.svn|.git|.anythingElseIwannaIgnore'

OR

find . -type f -print0 | xargs -0 egrep messages. | grep -Ev '.svn|.git|.anythingElseIwannaIgnore'
1
geminiimatt

Das funktioniert bei mir in der Unix-Eingabeaufforderung

gfind.\(-not -wholename '* \. svn *' \) -type f -name 'messages. *' -exec grep -Iw uint {} +

Der obige Befehl listet DATEIEN auf, die nicht mit .svn übereinstimmen, und führt das von Ihnen erwähnte grep aus.

1
Felix