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 ?
Réponses
Trop de publicités?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.
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)
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.
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'
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).
- Réponses précédentes
- Plus de réponses