Est `ls -f | grep -c. le moyen le plus rapide de compter les fichiers dans le répertoire, lors de l’utilisation du système POSIX / Unix (Big Data)?

J’avais l’habitude de faire le ls path-to-whatever| wc -l ls path-to-whatever| wc -l , jusqu’à ce que je découvre que cela consum énormément de mémoire. Puis je me suis déplacé pour find path-to-whatever -name "*" | wc -l find path-to-whatever -name "*" | wc -l , qui semble consumr beaucoup de mémoire gracieuse, quel que soit le nombre de fichiers que vous avez.

Ensuite, j’ai appris que ls est surtout lent et moins efficace en mémoire en raison du sorting des résultats. En utilisant ls -f | grep -c . ls -f | grep -c . , on obtiendra des résultats très rapides; le seul problème est que les noms de fichiers peuvent contenir des “sauts de ligne”. Cependant, c’est un problème très mineur pour la plupart des cas d’utilisation.

Est-ce le moyen le plus rapide de compter les fichiers?

EDIT / Réponse possible: Il semble que certaines versions de ls, find, etc. aient été signalées avec plus de 8 millions de fichiers (à confirmer). Pour réussir avec un très grand nombre de fichiers (je pense que> 2,2 milliards), il faut utiliser l’appel système getdents64 au lieu de getdents, ce qui peut être fait avec la plupart des langages de programmation, qui prennent en charge les normes POSIX. Certains systèmes de fichiers peuvent offrir des méthodes non POSIX plus rapides pour compter les fichiers.

Une façon serait d’utiliser readdir et de compter les entrées (dans un répertoire). Ci-dessous je compte le fichier régulier et en utilisant d_type==DT_REG qui est disponible pour les systèmes d’exploitation et les FS limités ( man readdir et voir les NOTES) mais vous pouvez juste commenter cette ligne et compter toutes les entrées de dir:

 #include  #include  int main (int argc, char *argv[]) { struct dirent *entry; DIR *dirp; long long c; // 64 bit if(argc<=1) // require dir return 1; dirp = opendir (argv[1]); if (dirp == NULL) { // dir not found return 2; } while ((entry = readdir(dirp)) != NULL) { if(entry->d_type==DT_REG) c++; // printf ("%s\n", entry->d_name); // for outputing filenames } printf ("%lli\n", c); closedir (dirp); return 0; } 

Complie et exécute:

 $ gcc code.c $ ./a.out ~ 254 

(J’ai besoin de nettoyer mon répertoire personnel 🙂

Modifier:

J’ai touché un 1000000 fichiers dans un répertoire et effectuer une comparaison rapide (meilleur utilisateur + 5 systèmes présentés):

 $ time ls -f | grep -c . 1000005 real 0m1.771s user 0m0.656s sys 0m1.244s $ time ls -f | wc -l 1000005 real 0m1.733s user 0m0.520s sys 0m1.248s $ time ../a.out . 1000003 real 0m0.474s user 0m0.048s sys 0m0.424s 

Edit 2 :

Comme demandé dans les commentaires:

 $ time ./a.out testdir | wc -l 1000004 real 0m0.567s user 0m0.124s sys 0m0.468s