Des alternatives plus rapides pour «trouver» et «localiser»?

22

J'aimerai utiliser "trouver" et localiser "pour rechercher des fichiers source dans mon projet, mais leur exécution prend beaucoup de temps. Existe-t-il des alternatives plus rapides à ces programmes que je ne connais pas, ou des moyens d'accélérer les performances de ces programmes?

benhsu
la source
2
locatedevrait déjà être assez rapide, étant donné qu'il utilise un index pré-construit (la principale mise en garde étant qu'il doit être mis à jour), tout en finddevant lire les listes de répertoires.
afrazier
2
Quelle localisation utilisez-vous? mlocate est plus rapide que slocate de loin (notez que quel que soit le paquet que vous avez installé, la commande est toujours localisée, alors vérifiez votre gestionnaire de paquets)
Paul
@benhsu, lorsque j'exécute find /usr/src -name fprintf.csur ma machine de bureau OpenBSD, il renvoie les emplacements de ces fichiers source en moins de 10 secondes. locate fprintf.c | grep '^/usr/src.*/fprintf.c$'revient en moins d'une seconde. Quelle est votre définition de "long time to run" et comment utilisez-vous findet locate?
Kusalananda
@Paul, j'utilise mlocate.
benhsu
@KAK, je voudrais utiliser la sortie de find / Locate pour ouvrir un fichier dans emacs. le cas d'utilisation que j'ai à l'esprit est, je souhaite modifier le fichier, je tape le nom du fichier (ou une expression rationnelle correspondant au nom du fichier) dans emacs, et emacs utilisera find / Locate pour afficher une liste des fichiers qui lui correspondent, je vais donc aimer le temps de réponse assez rapide pour être interactif (moins de 1 seconde). J'ai environ 3 millions de fichiers dans $ HOME, une chose que je peux faire est de faire en sorte que ma commande find supprime certains fichiers.
benhsu

Réponses:

16

Recherche de fichiers source dans un projet

Utilisez une commande plus simple

En général, la source d'un projet est susceptible d'être à un seul endroit, peut-être dans quelques sous-répertoires imbriqués à pas plus de deux ou trois profondeurs, vous pouvez donc utiliser une commande (éventuellement) plus rapide telle que

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

Utiliser les métadonnées du projet

Dans un projet C, vous auriez généralement un Makefile. Dans d'autres projets, vous pouvez avoir quelque chose de similaire. Ceux-ci peuvent être un moyen rapide d'extraire une liste de fichiers (et leurs emplacements), d'écrire un script qui utilise ces informations pour localiser les fichiers. J'ai un script "sources" pour pouvoir écrire des commandes comme grep variable $(sources programname).

Accélérer la recherche

Recherchez moins d'endroits, au lieu de les find / …utiliser find /path/to/project …si possible. Simplifiez autant que possible les critères de sélection. Utilisez des pipelines pour différer certains critères de sélection si cela est plus efficace.

Vous pouvez également limiter la profondeur de la recherche. Pour moi, cela améliore beaucoup la vitesse de «recherche». Vous pouvez utiliser le commutateur -maxdepth. Par exemple, "-maxdepth 5"

Accélérer la localisation

Assurez-vous qu'il indexe les emplacements qui vous intéressent. Lisez la page de manuel et utilisez les options appropriées à votre tâche.

   -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.

Supprimer le besoin de recherche

Peut-être que vous cherchez parce que vous avez oublié où quelque chose est ou n'a pas été dit. Dans le premier cas, rédiger des notes (documentation), dans le second, demander? Les conventions, les normes et la cohérence peuvent beaucoup aider.

RedGrittyBrick
la source
10

J'ai utilisé la partie "accélérer la localisation" de la réponse de RedGrittyBrick. J'ai créé une plus petite base de données:

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

puis l'a pointé locatedu doigt :locate -d /home/benhsu/ben.db

benhsu
la source
6

Une tactique que j'utilise consiste à appliquer l' -maxdepthoption avec find:

find -maxdepth 1 -iname "*target*"

Répétez avec des profondeurs croissantes jusqu'à ce que vous trouviez ce que vous cherchez, ou que vous en ayez assez de regarder. Les premières itérations sont susceptibles de revenir instantanément.

Cela garantit que vous ne perdez pas de temps à regarder à travers les profondeurs de sous-arbres massifs lorsque ce que vous recherchez est plus susceptible d'être près de la base de la hiérarchie.


Voici un exemple de script pour automatiser ce processus (Ctrl-C lorsque vous voyez ce que vous voulez):

(
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
)

Notez que la redondance inhérente impliquée (chaque passage devra parcourir les dossiers traités dans les passes précédentes) sera largement optimisée grâce à la mise en cache du disque.

Pourquoi findcet ordre de recherche n'est-il pas une fonction intégrée? Peut-être parce que ce serait compliqué / impossible à implémenter si vous supposiez que la traversée redondante était inacceptable. L'existence de l' -depthoption laisse entrevoir la possibilité, mais hélas ...

nobar
la source
1
... effectuant ainsi une recherche "étendue".
nobar
3

Une autre solution simple consiste à utiliser un globbing de shell étendu plus récent. Autoriser:

  • bash: shopt -s globstar
  • ksh: set -o globstar
  • zsh: déjà activé

Ensuite, vous pouvez exécuter des commandes comme celle-ci dans le répertoire source de niveau supérieur:

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

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

Cela a l'avantage de rechercher récursivement dans tous les sous-répertoires et est très rapide.

dannyw
la source
3

The Silver Searcher

Vous pourriez le trouver utile pour rechercher très rapidement le contenu d'un grand nombre de fichiers de code source. Tapez simplement ag <keyword>. Voici une partie de la sortie de mon apt show silversearcher-ag:

Je l'utilise habituellement avec:

-G --file-search-regex PATTERN Rechercher uniquement les fichiers dont les noms correspondent à PATTERN.

ag -G "css$" important

capture d'écran

Pablo A
la source
1
le de ripgrep de algorythme est prétendument plus rapide que silversearch, et il honore également les .gitignorefichiers et skips .git, .svn, .hg.. dossiers.
ccpizza
@ccpizza Alors? Le Silver Searcher honore .gitignoreet ignore également les fichiers cachés et binaires par défaut. Ont également plus de contributeurs, plus de stars sur Github (14700 vs 8300) et sont déjà sur des repos de distributions de maires. Veuillez fournir une comparaison fiable et mise à jour des sources tierces. Néanmoins, ripgrepressemble à un excellent logiciel.
Pablo A
bon à savoir! Je ne suis en aucun cas affilié à un ou plusieurs auteurs ripgrep, cela correspondait à mes besoins, j'ai donc arrêté de chercher d'autres options.
ccpizza
Le chercheur d'argent respecte .gitignoreégalement. Cela dit, rgc'est absolument incroyable. Tout d'abord, il prend en charge unicode. D'après mon expérience, rgau moins deux fois plus rapide que ag(YMMV), je suppose que c'est dû à l'analyseur regex de Rust, qui n'était évidemment pas encore prêt dans les années agétait nouveau. rgpeut donner une sortie déterministe (mais ne le fait pas par défaut), il peut mettre sur liste noire les types de fichiers où agne peut que figurer sur la liste blanche, il peut ignorer les fichiers en fonction de la taille (bye bye logs). J'utilise toujours agau cas où j'aurais besoin d'une correspondance multiligne, ce qui rgne peut pas le faire.
Le Pellmeister
2

Pour trouver un remplacement, consultez fd . Il a une interface plus simple / plus intuitive que la commande find originale, et est un peu plus rapide.

Keith Hughitt
la source