J'ai un répertoire avec des fichiers cca 26 000 et j'ai besoin de grep dans tous ces fichiers. Le problème est que j'en ai besoin le plus rapidement possible, il n'est donc pas idéal de créer un script où grep prendra le nom d'un fichier de la commande find et écrira des correspondances dans le fichier. Avant le problème de la "liste des arguments trop longue", il a fallu environ 2 minutes au cca pour grep dans tous ces fichiers. Des idées comment le faire? edit: il y a un script qui crée tout le temps de nouveaux fichiers, il n'est donc pas possible de mettre tous les fichiers dans des répertoires différents.
files
grep
performance
user2778979
la source
la source
find
avecxargs
ougrep -R
Réponses:
Avec
find
:(
-type f
consiste à rechercher uniquement dans les fichiers normaux (excluant également les liens symboliques même s'ils pointent vers des fichiers normaux). Si vous souhaitez rechercher dans n'importe quel type de fichier à l'exception des répertoires (mais attention, il existe certains types de fichiers comme fifos ou / dev / zero qui vous ne voulez généralement pas lire), remplacez-type f
par le spécifique à GNU! -xtype d
(-xtype d
correspond aux fichiers du répertoire type après la résolution du lien symbolique)).Avec GNU
grep
:(mais attention, sauf si vous avez une version récente de GNU grep, cela suivra les liens symboliques lors de la descente dans les répertoires). Les fichiers non réguliers ne seront pas recherchés sauf si vous ajoutez une
-D read
option. Cependant, les versions récentes de GNUgrep
ne rechercheront toujours pas dans les liens symboliques.Les très anciennes versions de GNU
find
ne prenaient pas en charge la{} +
syntaxe standard , mais là, vous pouviez utiliser la non standard:Les performances sont susceptibles d'être liées aux E / S. C'est le temps de faire la recherche qui serait le temps nécessaire pour lire toutes ces données du stockage.
Si les données se trouvent sur une grappe de disques redondante, la lecture de plusieurs fichiers à la fois peut améliorer les performances (et les dégrader autrement). Si les performances ne sont pas liées aux E / S (car, par exemple, toutes les données sont dans le cache) et que vous disposez de plusieurs processeurs, l'utilisation simultanée
greps
peut également être utile. Vous pouvez le faire avecxargs
l'-P
option GNU .Par exemple, si les données se trouvent sur une matrice RAID1 avec 3 disques, ou si les données sont dans le cache et que vous avez 3 processeurs dont vous avez le temps:
(ici, utiliser
-n1000
pour générer un nouveaugrep
tous les 1000 fichiers, jusqu'à 3 fonctionnant en parallèle à la fois).Cependant, notez que si la sortie de
grep
est redirigée, vous vous retrouverez avec une sortie mal entrelacée des 3grep
processus, auquel cas vous voudrez peut-être l'exécuter comme:(sur un système GNU ou FreeBSD récent) ou utilisez l'
--line-buffered
option GNUgrep
.S'il
pattern
s'agit d'une chaîne fixe, l'ajout de l'-F
option pourrait améliorer les choses.Si ce ne sont pas des données de caractères multi-octets, ou si pour la correspondance de ce modèle, peu importe si les données sont des caractères multi-octets ou non, alors:
pourrait améliorer considérablement les performances.
Si vous finissez souvent par effectuer de telles recherches, vous souhaiterez peut-être indexer vos données à l'aide de l'un des nombreux moteurs de recherche disponibles.
la source
26000 fichiers dans un seul répertoire, c'est beaucoup pour la plupart des systèmes de fichiers. Il est probable qu'une partie importante du temps soit consacrée à la lecture de ce gros répertoire. Pensez à le diviser en répertoires plus petits avec seulement quelques centaines de fichiers chacun.
L'appel
find
ne peut expliquer les mauvaises performances que si vous le faites mal. C'est un moyen rapide de parcourir un répertoire et de vous assurer que vous ne risquez pas d'essayer d'exécuter une ligne de commande trop longue. Assurez-vous que vous utilisez-exec grep PATTERN {} +
, qui contient autant de fichiers que possible par appel de commande, et non-exec grep PATTERN {} \;
, qui s'exécutegrep
une fois par fichier: l'exécution de la commande une fois par fichier sera probablement beaucoup plus lente.la source
Si vous avez besoin de grep TOUS les fichiers plusieurs fois (comme vous l'avez dit, en exécutant un script), je suggérerais de regarder dans les disques RAM, d'y copier tous les fichiers puis de grep les fichiers plusieurs fois, cela accélérera votre recherche d'un facteur de au moins 100x.
Vous avez juste besoin de suffisamment de bélier. Sinon, vous devriez examiner l'indexation des fichiers, par exemple. dans lucene ou une base de données nosql, puis en exécutant des requêtes à ce sujet.
la source
grep
contre. Il y a aussi le fait que: "il y a un script qui crée tout le temps de nouveaux fichiers, donc il n'est pas possible de mettre tous les fichiers dans des répertoires différents."Tous les fichiers du répertoire
avec récursivement
la source
.
place de*
).*
exclura les fichiers de points (bien qu'avec -R, pas ceux des répertoires récursifs). -R par opposition à -r suit les liens symboliques même avec les versions récentes de GNU grep. Vous aurez également un problème avec les fichiers du répertoire actuel dont le nom commence par-