Jai essayé les deux commandes et la commande find | grep "filename" est plusieurs fois plus lente que la simple find "filename" commande.

Quelle serait une explication correcte de ce comportement?

Commentaires

  • Vous listent chaque fichier avec find, puis transmettent les données à grep pour quil les traite. Avec find utilisé dessus ‘, vous manquez létape de passer chaque fichier listé à grep pour analyser la sortie. Ce sera donc plus rapide.
  • Plus lent dans quel sens? Les commandes prennent-elles un temps dexécution différent?
  • Je ne peux ‘ reproduire cela localement. Si quoi que ce soit, time find "$HOME" -name '.profile' signale une durée plus longue que time find "$HOME" | grep -F '.profile'. (17 contre 12).
  • @JenniferAnderson Jai couru les deux à plusieurs reprises. Les 17 et 12 secondes sont des moyennes. Et oui, la variante grep correspondra nimporte où dans le résultat find, alors quelle correspondra avec find -name ne correspondrait que exactement (dans ce cas).
  • Oui, find filename serait rapide . Jai un peu supposé que cétait une faute de frappe et que lOP signifiait find -name filename. Avec find filename, seul filename serait examiné (et rien dautre).

Réponse

(Je suppose que GNU find ici)

En utilisant uniquement

find filename 

serait rapide, car il renverrait simplement filename, ou les noms à lintérieur de filename sil sagit « dun répertoire, ou une erreur si ce nom nexistait pas dans le répertoire courant. Cest une opération très rapide, similaire à ls filename (mais récursive si filename est un répertoire).

Dans contraste,

find | grep filename 

permettrait à find de générer une liste de tous noms à partir de le répertoire courant et ci-dessous, que grep filtrerait alors. Ce serait évidemment une opération beaucoup plus lente.

Je suppose que ce qui était en fait prévu était

find . -type f -name "filename" 

Cela chercherait filename comme nom dun fichier normal nimporte où dans le répertoire actuel ou ci-dessous.

Ce sera aussi rapide (ou comparativement rapide) que find | grep filename, mais le grep la solution ferait correspondre filename au chemin complet de chaque nom trouvé, de la même manière que -path "*filename*" ferait avec find.


La confusion vient dun malentendu sur la façon dont find fonctionne.

Lutilitaire prend un certain nombre de chemins et renvoie tous les noms sous ces chemins.

Vous pouvez alors restreindre les noms renvoyés à laide de différents tests pouvant agir sur le nom du fichier, le chemin, lhorodatage, la taille du fichier, le type de fichier, etc.

Quand vous dites

find a b c 

vous demandez à find de lister tous les noms disponibles sous les trois chemins a, b et c. Sil sagit de noms de fichiers normaux dans le répertoire courant, ils seront renvoyés. Si lun dentre eux est le nom dun répertoire, il sera renvoyé avec tous les autres noms à lintérieur de ce répertoire.

Quand je le fais

find . -type f -name "filename" 

Ceci 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, cest-à-dire pas des répertoires, etc., avec -type f. Ensuite, il y a une autre restriction aux noms qui correspondent à filename en utilisant -name "filename". La chaîne filename peut être un modèle de remplacement de nom de fichier, tel que *.txt (noubliez pas de le citer!).

Exemple:

Ce qui suit semble « trouver » le fichier appelé .profile dans mon répertoire personnel:

$ pwd /home/kk $ find .profile .profile 

Mais en fait, il renvoie simplement tous les noms au chemin .profile (il ny a quun seul nom, celui de ce fichier).

Ensuite, cd monte dun niveau et réessaye:

$ cd .. $ pwd /home $ find .profile find: .profile: No such file or directory 

Le ne peut désormais trouver aucun chemin appelé .profile.

Cependant, si je l’obtiens pour regarder le répertoire courant, puis limite les noms renvoyés à seulement .profile , il trouve à partir de là également:

$ pwd /home $ find . -name ".profile" ./kk/.profile 

Commentaires

  • find filename renverrait uniquement filename si filename nétait pas de type répertoire (ou était de type répertoire, mais navait aucune entrée elle-même)

Réponse

Explication non technique: recherche de Jack dans une foule est plus rapide que de chercher tout le monde dans une foule et déliminer tout le monde sauf Jack.

Commentaires

  • Le problème est que lOP sattend à ce que Jack être la seule personne dans la foule. Si cest le cas, ils ‘ ont de la chance. find jack listera jack sil ‘ est un fichier appelé jack, ou tous les noms du répertoire sil ‘ est un répertoire. ‘ est une mauvaise compréhension du fonctionnement de find.

Réponse

Je nai pas encore compris le problème mais je peux fournir quelques informations supplémentaires.

Comme pour Kusalananda, lappel find | grep est clairement plus rapide sur mon système ce qui na pas beaucoup de sens. Au début, jai supposé une sorte de problème de mise en mémoire tampon; que lécriture sur la console ralentit le temps jusquau prochain appel système pour lire le nom de fichier suivant. Lécriture sur un tube est très rapide: environ 40MiB / s même pour les écritures de 32 octets (sur mon système plutôt lent; 300 Mo / s pour une taille de bloc de 1MiB). Jai donc supposé que find pouvait lire plus rapidement à partir du système de fichiers lors de lécriture dans un tube (ou fichier) afin que les deux opérations de lecture des chemins de fichiers et décriture sur la console puissent sexécuter en parallèle ( ce que find en tant que processus de thread unique ne peut pas faire seul.

Cest find « s fault

Comparaison des deux appels

:> time find "$HOME"/ -name "*.txt" >/dev/null real 0m0.965s user 0m0.532s sys 0m0.423s 

et

:> time find "$HOME"/ >/dev/null real 0m0.653s user 0m0.242s sys 0m0.405s 

montre que find fait quelque chose dincroyablement stupide (quoi que ce soit). Cest juste savère être assez incompétent pour exécuter -name "*.txt".

Cela pourrait dépendre du rapport entrée / sortie

Vous pourriez penser que find -name gagne sil y a très peu à écrire. Mais cela devient plus embarrassant pour find. Il perd même sil ny a rien à écrire du tout contre 200 000 fichiers (13 Mo de données de canal) pour grep:

time find /usr -name lwevhewoivhol 

find peut être aussi rapide que grep, bien que

Il savère que la stupidité de find « avec name ne sétend pas aux autres tests. Utilisez plutôt une expression régulière et le problème est parti:

:> time find "$HOME"/ -regex "\.txt$" >/dev/null real 0m0.679s user 0m0.264s sys 0m0.410s 

Je suppose que cela peut être considéré comme un bogue. Quelquun veut-il déposer un rapport de bogue? Ma version est find (GNU findutils) 4.6.0

Commentaires

  • Dans quelle mesure vos horaires sont-ils reproductibles? Si vous avez effectué le test -name en premier, il se peut quil ait été plus lent car le contenu du répertoire nétait pas mis en cache. (Lors du test de -name et -regex, je trouve quils prennent à peu près le même temps, au moins une fois que leffet de cache a été pris en compte. Bien sûr, il peut simplement sagir dune version différente de find …)
  • @psmears Bien sûr, jai fait ces tests plusieurs fois. Le problème de la mise en cache a été mentionné même dans les commentaires de la question avant la première réponse. Ma version find est find (GNU findutils) 4.6.0
  • Pourquoi est-il surprenant que lajout de -name '*.txt' ralentisse find? Il doit faire un travail supplémentaire, tester chaque nom de fichier.
  • @Barmar Dune part, ce travail supplémentaire peut être fait extrêmement rapidement. Dun autre côté, ce travail supplémentaire économise dautres travaux. find doit écrire moins de données. Et lécriture sur un tube est une opération beaucoup plus lente.
  • Lécriture sur un disque est très lente, lécriture sur un tube nest pas si mal, elle copie simplement dans un tampon du noyau. Notez que lors de votre premier test, écrire plus dans /dev/null a utilisé en quelque sorte moins de temps système.

Réponse

Remarque : Je suppose que vous voulez dire find . -name filename (sinon, vous « cherchez des choses différentes; find filename recherche en fait un chemin appelé filename , qui peut ne contenir presque aucun fichier, doù une sortie très rapide).


Supposons que vous ayez un répertoire contenant cinq mille fichiers. Sur la plupart des systèmes de fichiers, ces fichiers sont en fait stockés dans une structure arborescente , qui permet de localiser rapidement un fichier donné.

Ainsi, lorsque vous demandez à find de localiser un fichier dont le nom ne nécessite quune vérification, find vous le demandera pour ce fichier, et ce fichier uniquement, vers le système de fichiers sous-jacent, qui lira très peu de pages du stockage de masse. Donc, si le système de fichiers en vaut la peine, cette opération s’exécutera beaucoup plus rapidement que traversant l’arborescence entière pour récupérer toutes les entrées.

Lorsque vous demandez un find, mais cest exactement ce que vous faites, vous parcourez tout larbre, en lisant. Chaque. Unique. Entrée. Avec de grands répertoires, cela peut être un problème (cest exactement la raison pour laquelle plusieurs logiciels, ayant besoin de stocker beaucoup de fichiers sur le disque, créeront des « arborescences de répertoires » à deux ou trois composants: de cette façon, chaque feuille na besoin que de contenir moins de fichiers) .

Réponse

Supposons que le fichier / john / paul / george / ringo / beatles existe et le fichier que vous recherchez sappelle « stones »

find / stones 

find comparera « beatles » à « stones » et le lâchera quand le « s » et « b » ne correspondent pas .

find / | grep stones 

Dans ce cas, find passera « / john / paul / george / ringo / beatles » à grep et grep wil Je dois parcourir tout le chemin avant de déterminer si cest une correspondance.

grep fait donc beaucoup plus de travail, cest pourquoi cela prend plus de temps

Commentaires

  • Avez-vous essayé?
  • Le coût des comparaisons de chaînes (extrêmement simples et bon marché) est complètement éclipsé par le coût des E / S (ou simplement des appels système si mis en cache) des recherches de répertoire.
  • grep isn ‘ une comparaison de chaînes, sa comparaison dexpressions régulières qui signifie quil doit parcourir toute la chaîne jusquà ce quil trouve un match ou atteint la fin. Les recherches dans les répertoires sont les mêmes quoi quil arrive.
  • @Paranoid Hm, de quelle version de find parlez-vous? Cela ‘ ne ressemble en rien à la find I ‘ m utilisée dans debian.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *