Question

Y at-il une méthode sous Linux pour calculer le nombre de fichiers dans un répertoire (qui est, les enfants immédiats) O (1) (indépendamment du nombre de fichiers) sans avoir à la liste du répertoire en premier? Dans le cas contraire O (1), est-il un moyen raisonnablement efficace?

Je cherche une alternative à ls | wc -l.

Était-ce utile?

La solution

readdir est pas aussi cher que vous pouvez penser. Le don est d'éviter stat'ing chaque fichier, et (éventuellement) le tri de la sortie de ls.

/bin/ls -1U | wc -l

évite les alias dans votre shell, ne trie pas la sortie, et les listes 1 fichier par ligne (non strictement nécessaire, lorsque la tuyauterie de la sortie en wc).

La question initiale peut être reformulée comme « La structure de données d'un magasin de répertoire un compte du nombre d'entrées? », À laquelle la réponse est non. Il n'y a pas un moyen plus efficace des fichiers de comptage que readdir (2) / getdents (2).

Autres conseils

On peut obtenir le nombre de sous-répertoires d'un répertoire donné sans traverser toute la liste par stat'ing (stat (1) ou stat (2)) le répertoire donné et en observant le nombre de liens vers ce répertoire. Un répertoire donné avec les répertoires enfants N aura un nombre de liens de N + 2, un lien pour le « .. » entrée de chaque sous-répertoire, plus deux pour le « » et « .. » entrées du répertoire donné.

Cependant, on ne peut pas obtenir le nombre de tous les fichiers (si les fichiers réguliers ou sous-répertoires) sans parcourir toute la liste - qui est correct.

La commande "/ bin / ls -1U" n'obtenir toutes les entrées cependant. Il obtiendra que les entrées de répertoire qui ne commencent pas avec le caractère point (.). Par exemple, il ne compterait pas le fichier « .profile » trouvé dans de nombreux connexion répertoire $ HOME.

On peut utiliser la commande "/ bin / ls -f" ou la commande "/ bin / ls -ua" pour éviter le genre et obtenir toutes les entrées.

Peut-être malheureusement pour vos besoins, soit la commande « / bin / ls -f » ou la commande « / bin / ls -ua » aussi compter le « » et les entrées « .. » qui se trouvent dans chaque répertoire. Vous devrez soustraire 2 du compte pour éviter de compter ces deux entrées, comme dans ce qui suit:

expr `/bin/ls -f | wc -l` - 2     # Those are back ticks, not single quotes.

L'option --format = colonne unique (-1) ne soit pas nécessaire à la commande « / bin / ls -ua » lorsque redirigeant la sortie « ls », comme pour « wc » dans ce cas. La commande « ls » écrira automatiquement sa sortie dans une seule colonne si la sortie n'est pas un terminal.

L'option -U pour ls n'est pas dans Posix, et dans le ls de OS X, il a un sens différent de GNU ls, qui est qu'il fait -t et -l utilisation fois la création au lieu des temps de modification. -f est en POSIX comme une extension XSI. Le manuel de GNU ls décrit -f comme do not sort, enable -aU, disable -ls --color et -U comme do not sort; list entries in directory order.

décrit -f Posix comme ceci:

  

Force chaque argument à interpréter comme un répertoire et liste le nom trouvé dans chaque fente. Cette option doit désactiver -l, -t, -s et -r, et tournera sur -a; l'ordre est l'ordre dans lequel les entrées apparaissent dans le répertoire.

Les commandes comme ls|wc -l donnent le mauvais résultat lorsque les noms de fichiers contiennent des sauts de ligne.

En zsh vous pouvez faire quelque chose comme ceci:

a=(*(DN));echo ${#a}

D (glob_dots) comprend les fichiers dont le nom commence avec une période et N (null_glob) provoque la commande de ne pas provoquer une erreur dans un répertoire vide.

Ou même en bash:

shopt -s dotglob nullglob;a=(*);echo ${#a[@]}

Si IFS contient des chiffres ASCII, ajouter des guillemets doubles autour ${#a[@]}. Ajouter shopt -u failglob pour faire en sorte que failglob est hors service.

Une option portable est d'utiliser find:

find . ! -name . -prune|grep -c /

grep -c / peut être remplacé par wc -l si les noms de fichiers ne contiennent pas de nouvelles lignes. ! -name . -prune est une alternative portable -mindepth 1 -maxdepth 1.

Ou une autre alternative qui ne comprend généralement pas les fichiers dont le nom commence avec une période:

set -- *;[ -e "$1" ]&&echo "$#"

La commande ci-dessus inclut cependant les fichiers dont le nom commence avec une période où une option comme dotglob en bash ou glob_dots dans zsh est réglé. Lorsque * correspond à aucun fichier, les résultats de la commande une erreur dans zsh avec les paramètres par défaut.

J'ai utilisé cette command..works comme un charm..only pour changer le maxdepth..that est sous-répertoires

find * -maxdepth 0 -type d -exec sh -c "echo -n {} ' ' ; ls -lR {} | wc -l" \;

Je pense que vous pouvez avoir plus de contrôle sur ce en utilisant find:

find <path> -maxdepth 1 -type f -printf "." | wc -c
  • find -maxdepth 1 ne sera pas aller plus loin dans la hiérarchie des fichiers.
  • -type f permet de filtrer les fichiers seulement. De même, vous pouvez utiliser -type d pour les répertoires.
  • -printf "." imprime un point pour chaque match.
  • wc -c compte les caractères, il compte les points créés par le print ... ce qui signifie compter combien de fichiers existent dans le chemin donné.

Pour autant que je sache, il n'y a pas de meilleure alternative. Ces informations peuvent être hors-sujet à cette question et vous pouvez déjà savoir ce que sous répertoires Linux (en général sous Unix) sont tout fichier spécial qui contient la liste des autres fichiers (je comprends que les détails exacts dépendront de fichier spécifique système, mais cela est l'idée générale). Et il n'y a pas d'appel pour trouver le nombre total d'entrées sans traverser toute la liste. S'il vous plaît me faire corriger si je me trompe.

Pour le nombre de tous les fichiers dans un répertoire courant, essayez ceci:

ls -lR * | wc -l
utilisation

ls -1 | wc -l

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top