Schnellere Alternativen zum „Finden“ und „Lokalisieren“?

22

Ich würde gerne "find" und "locate" verwenden, um in meinem Projekt nach Quelldateien zu suchen, aber die Ausführung dauert sehr lange. Gibt es schnellere Alternativen zu diesen Programmen, die ich nicht kenne, oder Möglichkeiten, die Leistung zu beschleunigen? dieser Programme?

benhsu
quelle
2
locatesollte schon schnell genug sein, wenn man bedenkt, dass es einen vorgefertigten Index verwendet (der wichtigste Vorbehalt ist, dass es auf dem neuesten Stand gehalten werden muss), während finddie Verzeichnislisten gelesen werden müssen.
afrazier
2
Welchen Ort verwenden Sie? mlocate ist bei weitem schneller als slocate (Beachten Sie, dass das Kommando unabhängig vom installierten Paket immer noch lokalisiert ist, überprüfen Sie also Ihren Paketmanager)
Paul
@benhsu, wenn ich find /usr/src -name fprintf.cauf meiner OpenBSD-Desktop-Maschine laufe, werden die Speicherorte dieser Quelldateien in weniger als 10 Sekunden zurückgegeben. locate fprintf.c | grep '^/usr/src.*/fprintf.c$'kommt in weniger als einer Sekunde zurück. Was ist Ihre Definition von "langer Laufzeit" und wie verwenden Sie findund locate?
Kusalananda
@ Paul, ich benutze mlocate.
Benhsu
@KAK, ich möchte die Ausgabe von find / locate verwenden, um eine Datei in Emacs zu öffnen. Ich möchte die Datei bearbeiten, gebe den Dateinamen (oder einen regulären Ausdruck, der mit dem Dateinamen übereinstimmt) in emacs ein und emacs verwendet find / locate, um eine Liste der passenden Dateien aufzurufen. Daher möchte ich, dass die Reaktionszeit schnell genug ist, um interaktiv zu sein (unter 1 Sekunde). Ich habe ungefähr 3 Millionen Dateien in $ HOME. Eine Sache, die ich tun kann, ist, meinen Befehl find dazu zu bringen, einige der Dateien zu entfernen.
Benhsu

Antworten:

16

Suchen nach Quelldateien in einem Projekt

Verwenden Sie einen einfacheren Befehl

Im Allgemeinen befindet sich die Quelle für ein Projekt wahrscheinlich an einem Ort, möglicherweise in einigen wenigen Unterverzeichnissen, die nicht mehr als zwei oder drei Zeilen tief verschachtelt sind, sodass Sie einen (möglicherweise) schnelleren Befehl wie z

(cd /path/to/project; ls *.c */*.c */*/*.c)

Nutzen Sie Projekt-Metadaten

In einem C-Projekt haben Sie normalerweise ein Makefile. In anderen Projekten haben Sie möglicherweise etwas Ähnliches. Dies kann ein schneller Weg sein, um eine Liste von Dateien (und ihren Speicherorten) zu extrahieren. Schreiben Sie ein Skript, das diese Informationen verwendet, um Dateien zu lokalisieren. Ich habe ein "Quellen" -Skript, damit ich Befehle wie schreiben kann grep variable $(sources programname).

Schneller finden

Suchen Sie nach weniger Orten, anstatt sie zu find / …verwenden, find /path/to/project …wo dies möglich ist. Vereinfachen Sie die Auswahlkriterien so weit wie möglich. Verwenden Sie Pipelines, um einige Auswahlkriterien zu verschieben, wenn dies effizienter ist.

Sie können auch die Suchtiefe begrenzen. Für mich bedeutet dies eine erhebliche Verbesserung der Suchgeschwindigkeit. Sie können den Schalter -maxdepth verwenden. Zum Beispiel '-maxtiefe 5'

Schnellere Lokalisierung

Stellen Sie sicher, dass die Standorte indiziert werden, an denen Sie interessiert sind. Lesen Sie die Manpage und nutzen Sie die für Ihre Aufgabe geeigneten Optionen.

   -U <dir>
          Create slocate database starting at path <dir>.

   -d <path>
          --database=<path> Specifies the path of databases to search  in.


   -l <level>
          Security  level.   0  turns  security checks off. This will make
          searchs faster.   1  turns  security  checks  on.  This  is  the
          default.

Beseitigen Sie die Notwendigkeit der Suche

Vielleicht suchen Sie, weil Sie vergessen haben, wo etwas steht oder was nicht gesagt wurde. Im ersteren Fall schreiben Sie Notizen (Dokumentation), im letzteren fragen Sie? Konventionen, Standards und Konsistenz können sehr hilfreich sein.

RedGrittyBrick
quelle
10

Ich habe den Teil von RedGrittyBricks Antwort verwendet, der das Auffinden beschleunigt. Ich habe eine kleinere Datenbank erstellt:

updatedb -o /home/benhsu/ben.db -U /home/benhsu/ -e "uninteresting/directory1 uninteresting/directory2"

dann darauf hingewiesen locate:locate -d /home/benhsu/ben.db

benhsu
quelle
6

Eine Taktik, die ich benutze, besteht darin, die -maxdepthOption anzuwenden mit find:

find -maxdepth 1 -iname "*target*"

Wiederholen Sie dies mit zunehmender Tiefe, bis Sie das Gewünschte gefunden haben oder es müde wird, danach zu suchen. Die ersten paar Iterationen werden wahrscheinlich sofort zurückkehren.

Dies stellt sicher, dass Sie keine Zeit im Voraus mit dem Durchsuchen der Tiefen von massiven Teilbäumen verschwenden, wenn das, was Sie suchen, eher in der Nähe der Basis der Hierarchie liegt.


Hier ist ein Beispielskript zur Automatisierung dieses Prozesses (Strg-C, wenn Sie sehen, was Sie wollen):

(
TARGET="*target*"
for i in $(seq 1 9) ; do
   echo "=== search depth: $i"
   find -mindepth $i -maxdepth $i -iname "$TARGET"
done
echo "=== search depth: 10+"
find -mindepth 10 -iname $TARGET
)

Beachten Sie, dass die inhärente Redundanz (jeder Durchlauf muss die in den vorherigen Durchläufen verarbeiteten Ordner durchlaufen) durch das Zwischenspeichern von Datenträgern weitgehend optimiert wird.

Warum ist finddiese Suchreihenfolge nicht als integrierte Funktion verfügbar? Vielleicht, weil die Implementierung kompliziert oder unmöglich wäre, wenn Sie davon ausgehen, dass die redundante Überquerung inakzeptabel ist. Die Existenz der -depthOption deutet auf die Möglichkeit hin, aber leider ...

kein Balken
quelle
1
... also eine "Breitensuche" durchführen.
Nobar
3

Eine andere einfache Lösung ist die Verwendung von neuerem Extended Shell Globbing. Ermöglichen:

  • bash: shopt -s globstar
  • ksh: set -o globstar
  • zsh: bereits aktiviert

Anschließend können Sie im Quellverzeichnis der obersten Ebene folgende Befehle ausführen:

# grep through all c files
grep printf **/*.c

# grep through all files
grep printf ** 2>/dev/null

Dies hat den Vorteil, dass alle Unterverzeichnisse rekursiv durchsucht werden und dies sehr schnell geht.

dannyw
quelle
3

Der silberne Sucher

Sie fanden es möglicherweise nützlich, wenn Sie den Inhalt einer großen Anzahl von Quellcodedateien sehr schnell durchsuchen möchten. Einfach tippen ag <keyword>. Hier einige meiner Ausgaben apt show silversearcher-ag:

Ich benutze es normalerweise mit:

-G --file-search-regex PATTERN Nur Dateien suchen, deren Namen mit PATTERN übereinstimmen.

ag -G "css$" important

Bildschirmfoto

Pablo A
quelle
1
die der ripgrep algorythm ist angeblich schneller als silversearch, und es ehrt auch .gitignoreDateien und überspringt .git, .svn, .hg.. Ordner.
ccpizza
@ccpizza Also? Der Silver Searcher berücksichtigt .gitignoreund ignoriert standardmäßig auch versteckte und binäre Dateien. Haben Sie auch mehr Mitwirkende, mehr Sterne auf Github (14700 gegen 8300) und ist bereits auf Repos von Bürgermeister Distros. Bitte legen Sie einen aktualisierten, zuverlässigen Vergleich der Quellen von Drittanbietern vor. Trotzdem ripgrepsieht ein tolles Stück Software aus.
Pablo A
gut zu wissen! Ich bin ripgrepin keiner Weise mit einem oder mehreren Autoren verbunden. Es passt einfach zu meinen Anforderungen und ich habe aufgehört, nach anderen Optionen zu suchen.
ccpizza
Der silberne Sucher respektiert .gitignoreauch. Das heißt, rgist absolut erstaunlich. Zunächst einmal hat es Unicode-Unterstützung. Nach meiner Erfahrung rgdurchweg mindestens doppelt so schnell wie ag(YMMV), glaube ich, dass es an Rusts Regex-Parser liegt, der offensichtlich in den vergangenen Jahren noch nicht fertig agwar. rgKann deterministische Ausgaben liefern (aber nicht standardmäßig). Kann Dateitypen auf eine Blacklist setzen, bei denen agnur eine Whitelist zulässig ist. Kann Dateien basierend auf der Größe ignorieren (Bye-Bye-Protokolle). Ich verwende immer noch agfür den Fall, dass ich mehrzeiliges Matching benötige, was rgnicht möglich ist.
Der Pellmeister
2

Für einen Ersatz finden Sie unter fd . Es hat eine einfachere / intuitivere Oberfläche als der ursprüngliche Befehl find und ist viel schneller.

Keith Hughitt
quelle