131 votes

Quelle est la meilleure façon de compter les résultats des "recherches" ?

Ma solution actuelle serait la suivante find <expr> -exec printf '.' \; | wc -c mais cela prend beaucoup trop de temps lorsqu'il y a plus de 10000 résultats. Existe-t-il un moyen plus rapide/meilleur de procéder ?

164voto

Brian Agnew Points 143181

Pourquoi pas ?

find <expr> | wc -l

comme une solution simple et portable ? Votre solution originale est Lancement d'un nouveau processus printf pour chaque fichier individuel trouvé, et c'est très coûteux (comme vous venez de le constater).

Notez que ce calcul sera surestimé si vous avez des noms de fichiers avec des nouvelles lignes incorporées, mais si c'est le cas, je pense que vos problèmes sont un peu plus profonds.

100voto

sputnick Points 31663

Essayez plutôt ceci (exigez find 's -printf soutien) :

find <expr> -type f -printf '.' | wc -c

Il sera plus fiable et plus rapide que de compter les lignes.

Notez que j'utilise le find 's printf et non une commande externe.


Faisons un peu de banc :

$ ls -1
a
e
l
ll.sh
r
t
y
z

Mon benchmark snippet :

$ time find -type f -printf '.' | wc -c
8

real    0m0.004s
user    0m0.000s
sys     0m0.007s

Avec des lignes complètes :

$ time find -type f | wc -l
8

real    0m0.006s
user    0m0.003s
sys     0m0.000s

Donc ma solution est plus rapide =) (la partie importante est le real ligne)

7voto

John B Points 1534

Cette solution est certainement plus lente que d'autres solutions. find -> wc Il n'y a pas de solution ici, mais si vous vouliez faire autre chose avec les noms de fichiers en plus de les compter, vous pourriez read de la find sortie.

n=0
while read -r -d ''; do
    ((n++)) # count
    # maybe perform another act on file
done < <(find <expr> -print0)
echo $n

Il s'agit simplement d'une modification de une solution trouvée dans BashGuide qui gère correctement les fichiers dont les noms ne sont pas standard en faisant en sorte que la balise find délimiteur de sortie un octet NUL en utilisant print0 et de le lire en utilisant '' (octet NUL) comme délimiteur de boucle.

5voto

carlo Points 51

C'est mon countfiles dans mon ~/.bashrc (il est raisonnablement rapide, devrait fonctionner pour Linux et FreeBSD find et ne se laisse pas tromper par les chemins d'accès aux fichiers contenant des caractères de nouvelle ligne. wc ne compte que les octets NULs) :

countfiles () 
{ 
   command find "${1:-.}" -type f -name "${2:-*}" -print0 | 
       command tr -dc '\0' | command wc -c;
return 0
}

countfiles

countfiles ~ '*.txt'

4voto

Quasímodo Points 161

Conforme à POSIX et à l'épreuve des nouvelles lignes :

find /path -exec printf %c {} + | wc -c

Et, d'après mes tests dans / Le système de gestion de l'information de la Commission européenne est plus lent que les autres solutions, qui ne sont pas à l'épreuve des nouvelles lignes ou qui ne sont pas portables.

Notez le + au lieu de \; . C'est crucial pour les performances, car \; donne naissance à un printf par nom de fichier, alors que + donne autant de noms de fichiers qu'il peut à une seule printf commande. (Et dans le cas possible où il y a trop d'arguments, Find génère intelligemment de nouveaux Printfs à la demande pour y faire face, donc c'est comme si

{ 
  printf %c very long argument list1
  printf %c very long argument list2
  printf %c very long argument list3 
} | wc -c

ont été appelés).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X