J'ai essayé les deux commandes et la commande find | grep 'filename'
est beaucoup plus lente que la find 'filename'
commande simple .
Quelle serait une explication appropriée de ce comportement?
command-line
grep
find
search
file-search
yoyo_fun
la source
la source
time find "$HOME" -name '.profile'
rapporte un temps plus long quetime find "$HOME" | grep -F '.profile'
. (17s contre 12s).grep
variation correspondra n'importe où dans lefind
résultat, alors que la correspondance avecfind -name
ne correspondra exactement (dans ce cas).find filename
serait rapide . J'ai supposé que c'était une faute de frappe et que l'OP signifiaitfind -name filename
. Avecfind filename
, seulfilename
serait examiné (et rien d'autre).Réponses:
(Je suppose que GNU
find
ici)En utilisant juste
serait rapide, car il retournerait simplement
filename
, ou les noms à l'intérieurfilename
s'il s'agit d'un répertoire, ou une erreur si ce nom n'existait pas dans le répertoire courant. C'est une opération très rapide, similaire àls filename
(mais récursive s'ilfilename
s'agit d'un répertoire).En revanche,
permettrait
find
de générer une liste de tous les noms à partir du répertoire courant et ci-dessous, quigrep
filtrerait ensuite. Ce serait évidemment une opération beaucoup plus lente.Je suppose que ce qui était réellement prévu était
Ce serait
filename
le nom d'un fichier normal n'importe où dans le répertoire courant ou en dessous.Ce sera aussi rapide (ou relativement rapide) que
find | grep filename
, mais lagrep
solution correspondraitfilename
au chemin complet de chaque nom trouvé, de manière similaire à ce qui-path '*filename*'
serait fait avecfind
.La confusion vient d'un malentendu sur le
find
fonctionnement.L'utilitaire prend un certain nombre de chemins et renvoie tous les noms sous ces chemins.
Vous pouvez ensuite restreindre les noms retournés à l'aide de divers tests qui peuvent agir sur le nom de fichier, le chemin, l'horodatage, la taille du fichier, le type de fichier, etc.
Quand tu dis
vous demandez
find
de lister tous les noms disponibles sous les trois cheminsa
,b
etc
. S'il se trouve que ce sont des noms de fichiers normaux dans le répertoire courant, ils seront retournés. Si l'un d'eux se trouve être le nom d'un répertoire, il sera renvoyé avec tous les autres noms à l'intérieur de ce répertoire.Quand je fais
Cela génère une liste de tous les noms dans le répertoire courant (
.
) et ci-dessous. Ensuite, il restreint les noms à ceux des fichiers normaux, c'est-à-dire pas des répertoires, etc. avec-type f
. Ensuite, il y a une autre restriction aux noms qui correspondent à l'filename
utilisation-name 'filename'
. La chaînefilename
peut être un modèle de remplacement de nom de fichier, tel que*.txt
(n'oubliez pas de le citer!).Exemple:
Ce qui suit semble "trouver" le fichier appelé
.profile
dans mon répertoire personnel:Mais en fait, il retourne juste tous les noms sur le chemin
.profile
(il n'y a qu'un seul nom, et c'est de ce fichier).Ensuite, je
cd
monte d'un niveau et réessaye:La
find
commande ne trouve plus aucun chemin appelé.profile
.Cependant, si je le fais regarder le répertoire en cours, puis restreindre les noms retournés à seulement
.profile
, il le trouve également à partir de là:la source
find filename
ne retournerait quefilename
s'ilfilename
n'était pas de type répertoire (ou était de type répertoire, mais n'avait aucune entrée elle-même)Explication non technique: rechercher Jack dans une foule est plus rapide que rechercher tout le monde dans une foule et éliminer tout de la considération sauf Jack.
la source
find jack
listerajack
s'il s'agit d'un fichier appeléjack
, ou tous les noms du répertoire s'il s'agit d'un répertoire. C'est une mauvaise compréhension dufind
fonctionnement.Je n'ai pas encore compris le problème, mais je peux fournir quelques informations supplémentaires.
Comme pour Kusalananda, l'
find | grep
appel est clairement plus rapide sur mon système, ce qui n'a pas beaucoup de sens. Au début, j'ai supposé une sorte de problème de mise en mémoire tampon; que l'écriture dans la console ralentit le temps jusqu'au prochain appel système pour lire le nom de fichier suivant. L'écriture sur un tube est très rapide: environ 40 Mo / s même pour des écritures de 32 octets (sur mon système plutôt lent; 300 Mo / s pour une taille de bloc de 1 Mo). J'ai donc supposé quefind
le système de fichiers peut lire plus rapidement lors de l'écriture dans un canal (ou fichier) afin que les deux opérations de lecture des chemins de fichier et d'écriture sur la console puissent s'exécuter en parallèle (ce qui, enfind
tant que processus à un seul thread, ne peut pas se faire tout seul.C'est de
find
la fauteComparaison des deux appels
et
montre que cela
find
fait quelque chose d'incroyablement stupide (quoi que ce soit). Il s'avère juste être assez incompétent à exécuter-name '*.txt'
.Peut dépendre du rapport entrée / sortie
Vous pourriez penser que cela
find -name
gagne s'il y a très peu à écrire. Mais ça devient plus embarrassantfind
. Il perd même s'il n'y a rien à écrire contre des fichiers 200K (13M de données de pipe) pourgrep
:find
peut être aussi rapide quegrep
, bien queIl s'avère que cette
find
stupiditéname
ne s'étend pas aux autres tests. Utilisez plutôt une expression régulière et le problème a disparu:Je suppose que cela peut être considéré comme un bug. Quiconque souhaite déposer un rapport de bogue? Ma version est find (GNU findutils) 4.6.0
la source
-name
test en premier, il peut avoir été plus lent car le contenu du répertoire n'est pas mis en cache. (Lors des tests-name
et-regex
je trouve qu'ils prennent à peu près le même temps, au moins une fois que l'effet de cache a été pris en considération. Bien sûr, il peut s'agir simplement d'une version différente defind
...)find
version est find (GNU findutils) 4.6.0-name '*.txt'
ralentissefind
? Il doit faire un travail supplémentaire, tester chaque nom de fichier.find
doit écrire moins de données. Et écrire sur un tuyau est une opération beaucoup plus lente./dev/null
quelque sorte utiliser moins de temps système.Remarque : je suppose que vous voulez dire
find . -name filename
(sinon, vous cherchez des choses différentes;find filename
regarde en fait dans un chemin appelé nom de fichier , qui pourrait ne contenir presque aucun fichier, donc sortir très rapidement).Supposons que vous ayez un répertoire contenant cinq mille fichiers. Sur la plupart des systèmes de fichiers, ces fichiers sont stockés dans un arbre la structure , ce qui permet de localiser rapidement une fichier donné.
Alors , quand vous demandez
find
de trouver un fichier dont le nom nécessite la vérification, nefind
se demande pour ce fichier, et ce fichier uniquement, le système de fichiers sous - jacente, qui va lire très peu de pages de la mémoire de masse. Donc, si le système de fichiers vaut son sel, cette opération s'exécutera beaucoup plus rapidement que de parcourir l'arborescence entière pour récupérer toutes les entrées.Lorsque vous demandez simplement
find
mais c'est exactement ce que vous faites, vous parcourez tout l'arbre, en lisant. Chaque. Célibataire. Entrée. Avec de gros répertoires, cela pourrait être un problème (c'est exactement la raison pour laquelle plusieurs logiciels, ayant besoin de stocker de nombreux fichiers sur le disque, créeront des "arborescences de répertoires" de deux ou trois composants en profondeur: de cette façon, chaque feuille ne doit contenir que moins des dossiers).la source
Supposons que le fichier / john / paul / george / ringo / beatles existe et que le fichier que vous recherchez s'appelle «pierres»
find comparera les «beatles» aux «pierres» et les déposera lorsque les «s» et les «b» ne correspondent pas.
Dans ce cas, find passera '/ john / paul / george / ringo / beatles' à grep et grep devra se frayer un chemin à travers tout le chemin avant de déterminer s'il s'agit d'une correspondance.
grep fait donc beaucoup plus de travail, c'est pourquoi cela prend plus de temps
la source