GNU/Linux >> Tutoriels Linux >  >> Linux

Grep récursif Vs Find / -type F -exec Grep {} ; Lequel est le plus efficace/rapide ?

Qu'est-ce qui est le plus efficace pour trouver quels fichiers d'un système de fichiers entier contiennent une chaîne :grep récursif ou rechercher avec grep dans une instruction exec ? Je suppose que find serait plus efficace car vous pouvez au moins effectuer un filtrage si vous connaissez l'extension de fichier ou une expression régulière qui correspond au nom de fichier, mais lorsque vous ne connaissez que -type f ce qui est mieux? GNU grep 2.6.3 ; trouver (GNU findutils) 4.4.2

Exemple :

grep -r -i 'the brown dog' /

find / -type f -exec grep -i 'the brown dog' {} ;

Réponse acceptée :

Je ne suis pas sûr :

grep -r -i 'the brown dog' /*

c'est vraiment ce que tu voulais dire. Cela signifierait grep récursivement dans tous les fichiers et répertoires non cachés dans / (mais regardez toujours à l'intérieur des fichiers cachés et des répertoires à l'intérieur de ceux-ci).

En supposant que vous vouliez dire :

grep -r -i 'the brown dog' /

Quelques points à noter :

  • Pas tous grep les implémentations prennent en charge -r . Et parmi ceux qui le font, les comportements diffèrent :certains suivent des liens symboliques vers des répertoires lors de la traversée de l'arborescence des répertoires (ce qui signifie que vous pouvez finir par chercher plusieurs fois dans le même fichier ou même exécuter des boucles infinies), d'autres non. Certains regarderont à l'intérieur des fichiers de périphérique (et cela prendra un certain temps dans /dev/zero par exemple) ou des tubes ou des fichiers binaires…, certains ne le feront pas.
  • C'est efficace comme grep commence à chercher à l'intérieur des fichiers dès qu'il les découvre. Mais pendant qu'il regarde dans un fichier, il ne cherche plus d'autres fichiers à rechercher (ce qui est probablement aussi bien dans la plupart des cas)

Votre :

find / -type f -exec grep -i 'the brown dog' {} ;

(suppression du -r qui n'avait pas de sens ici) est terriblement inefficace car vous exécutez un grep par dossier. ; ne doit être utilisé que pour les commandes qui n'acceptent qu'un seul argument. De plus ici, car grep ne regarde que dans un seul fichier, il n'imprimera pas le nom du fichier, vous ne saurez donc pas où se trouvent les correspondances.

Vous ne regardez pas à l'intérieur des fichiers de périphérique, des canaux, des liens symboliques…, vous ne suivez pas les liens symboliques, mais vous êtes toujours potentiellement à l'intérieur de choses comme /proc/mem .

find / -type f -exec grep -i 'the brown dog' {} +

serait beaucoup mieux car aussi peu de grep commandes que possible seraient exécutées. Vous obtiendrez le nom du fichier à moins que la dernière exécution ne comporte qu'un seul fichier. Pour cela il vaut mieux utiliser :

find / -type f -exec grep -i 'the brown dog' /dev/null {} +

ou avec GNU grep :

find / -type f -exec grep -Hi 'the brown dog' {} +

Notez que grep ne sera pas lancé avant find a trouvé suffisamment de fichiers pour qu'il puisse mâcher, il y aura donc un délai initial. Et find ne continuera pas à rechercher d'autres fichiers jusqu'au précédent grep est revenu. L'allocation et la transmission de la grande liste de fichiers ont un impact (probablement négligeable), donc dans l'ensemble, cela sera probablement moins efficace qu'un grep -r qui ne suit pas le lien symbolique ou ne regarde pas à l'intérieur des appareils.

Connexe :Comment fonctionnent ${0##*/} et ${0%/*} ?

Avec les outils GNU :

find / -type f -print0 | xargs -r0 grep -Hi 'the brown dog'

Comme ci-dessus, aussi peu de grep autant d'instances que possible seront exécutées, mais find continuera à chercher d'autres fichiers pendant le premier grep l'invocation regarde à l'intérieur du premier lot. Cela peut ou non être un avantage cependant. Par exemple, avec des données stockées sur des disques durs rotatifs, find et grep l'accès aux données stockées à différents emplacements sur le disque ralentira le débit du disque en provoquant un déplacement constant de la tête du disque. Dans une configuration RAID (où find et grep peut accéder à différents disques) ou sur des SSD, cela peut faire une différence positive.

Dans une configuration RAID, l'exécution de plusieurs fichiers concurrents grep les invocations pourraient également améliorer les choses. Toujours avec les outils GNU sur stockage RAID1 avec 3 disques,

find / -type f -print0 | xargs -r0 -P2 grep -Hi 'the brown dog'

pourrait augmenter considérablement les performances. Notez cependant que le second grep ne sera démarré qu'une fois que suffisamment de fichiers auront été trouvés pour remplir le premier grep commande. Vous pouvez ajouter un -n option pour xargs pour que cela se produise plus tôt (et passer moins de fichiers par grep appel).

Notez également que si vous redirigez xargs sortie vers autre chose qu'un terminal, puis le greps s commenceront à mettre en mémoire tampon leur sortie, ce qui signifie que la sortie de ces grep s seront probablement entrelacés de manière incorrecte. Vous devez utiliser stdbuf -oL (lorsque disponible comme sur GNU ou FreeBSD) sur eux pour contourner cela (vous pouvez toujours avoir des problèmes avec de très longues lignes (généralement> 4KiB)) ou demandez à chacun d'écrire sa sortie dans un fichier séparé et de les concaténer à la fin.

Ici, la chaîne que vous recherchez est fixe (pas une expression régulière) donc en utilisant le -F l'option peut faire une différence (peu probable car grep les implémentations savent déjà comment optimiser cela).

Une autre chose qui pourrait faire une grande différence est de fixer la locale à C si vous êtes dans une locale multi-octet :

find / -type f -print0 | LC_ALL=C xargs -r0 -P2 grep -Hi 'the brown dog'

Pour éviter de regarder à l'intérieur de /proc , /sys …, utilisez -xdev et spécifiez les systèmes de fichiers dans lesquels vous souhaitez effectuer la recherche :

LC_ALL=C find / /home -xdev -type f -exec grep -i 'the brown dog' /dev/null {} +

Ou élaguez les chemins que vous souhaitez exclure explicitement :

LC_ALL=C find / ( -path /dev -o -path /proc -o -path /sys ) -prune -o 
  -type f -exec grep -i 'the brown dog' /dev/null {} +

Linux
  1. Rechercher le répertoire d'exclusion ?

  2. Obtenir l'option -exec dans Find To Work ?

  3. Sortir de la recherche si un -exec échoue ?

  4. Comment trouver plusieurs chaînes dans des fichiers ? ?

  5. bash trouver des répertoires

Commande Grep sous Linux (Rechercher du texte dans des fichiers)

Comment trouver une chaîne dans un fichier sous Linux

Rechercher du texte dans des fichiers sous Linux à l'aide de grep

trouver -exec cmd {} + vs | xarg

trouver -exec une fonction shell sous Linux ?

Qu'est-ce qui est le plus efficace - la compression tar ou zip ? Quelle est la différence entre tar et zip ?