Comment obtenir un nombre de fichiers dans un répertoire à l'aide de la ligne de commande?

194

J'ai un répertoire avec un grand nombre de fichiers. Je ne vois pas de lscommutateur pour fournir le compte. Existe-t-il une magie en ligne de commande pour obtenir un nombre de fichiers?

Blake
la source
tree . | tailou tree -a . | taild'inclure des fichiers / répertoires cachés, treeest récursif si c'est ce que vous voulez.
CodyChan

Réponses:

240

Utilisation d'une définition large de "fichier"

ls | wc -l

(notez qu'il ne compte pas les fichiers cachés et suppose que les noms de fichiers ne contiennent pas de caractères de nouvelle ligne).

Pour inclure les fichiers cachés (à l'exception de .et ..) et éviter les problèmes de caractères de nouvelle ligne, procédez comme suit:

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

Ou récursivement:

find .//. ! -name . -print | grep -c //
James Roth
la source
23
wcest un programme "compte de mots". Le -lcommutateur le fait compter les lignes. Dans ce cas, il compte les lignes dans la sortie de ls. C’est toujours ainsi que j’ai appris à obtenir un nombre de fichiers pour un répertoire donné.
Sandy
20
s'il vous plaît ajouter une note qui lsfait ls -1si la sortie est un tuyau.
Lesmana
6
cela ne contient pas tout dans un répertoire - vous avez manqué des fichiers de points et vous avez également collecté quelques lignes supplémentaires. Un répertoire vide retournera quand même 1 ligne. Et si vous appelez ls -la, vous obtiendrez trois lignes dans le répertoire. Vous voulez ls -lA | wc -lignorer les entrées .et ... Cependant, vous serez quand même un par un.
1
Un répertoire vide renvoie 0 pour moi
James Roth
2
Une approche corrigée, qui ne compterait pas deux fois les fichiers avec des nouvelles lignes dans le nom, serait la suivante: ls -q | wc -l- notez que les fichiers cachés ne seront toujours pas comptés par cette approche et que les répertoires seront comptés.
godlygeek
30

Pour une définition étroite du fichier:

 find . -maxdepth 1 -type f | wc -l
Maciej Piechotka
la source
Et vous pouvez bien sûr omettre le -maxdepth 1comptage récursif des fichiers (ou l'ajuster à la profondeur de recherche maximale souhaitée).
user7089
1
Si vous avez un fichier dont le nom contient une nouvelle ligne, cette approche le comptera deux fois de manière incorrecte.
godlygeek
7
Une approche corrigée, qui ne compterait pas deux fois les fichiers avec des nouvelles lignes dans le nom, serait la suivante:find -maxdepth 1 -type f -printf "\n" | wc -l
godlygeek
+1 Autoriser les fichiers cachés et ignorer les répertoires
Michael Durrant
14
ls -1 | wc -l

...

$ ls --help | grep -- '  -1'
    -1                         list one file per line

...

$ wc --help | grep -- '  -l'
    -l, --lines            print the newline counts

PS: note ls - <numéro un> | wc - <lettre-l>

nicomen
la source
10
La plupart des versions de lsdo -1le font automatiquement lorsque la sortie est dirigée vers un canal.
Dennis Williamson
3
@ Dennis c'est intéressant, je ne savais pas qu'une application pouvait dire que sa sortie était dirigée vers un tuyau.
xenoterracide
1
J'ai édité cette version car elle est plus explicite. Bien que oui, ls utilise -1 s'il est connecté (essayez-le: ls | cat), je trouve la syntaxe -1 plus explicite.
Gabe.
3
@xenoterracide: In Bash:[[ -p /dev/stdin ]] && echo "stdin is from a pipe"
Dennis Williamson Le
2
Lors de mes tests, il était nettement plus rapide de fournir également l'option -f pour éviter le tri des noms de fichiers. Malheureusement, vous obtenez toujours la mauvaise réponse si vos noms de fichiers contiennent des nouvelles lignes.
Samuel Edwin Ward
10

La réponse la plus complète en utilisant ls/ wcpair est probablement

ls -Aq | wc -l

si vous voulez compter les fichiers de points, et

ls -q | wc -l

autrement.

  • -Aest de compter les fichiers de points, mais omettre .et ...
  • -qmake lsremplace les caractères non graphiques, en particulier le caractère de nouvelle ligne, avec ?, créant une ligne de sortie pour chaque fichier

Pour obtenir une sortie sur une ligne du lsterminal in (c.-à-d. Sans le canaliser dans wc), une -1option doit être ajoutée.

(comportement de lstesté avec coreutils 8.23)

Frax
la source
2
Comme vous l'avez dit, ce -1n'est pas nécessaire. Quant à "il gère les nouvelles lignes dans les noms de fichiers de manière sensible avec la sortie de la console" , cela est dû au -qcommutateur (que vous devriez utiliser à la place, -bcar il est portable) qui "Force chaque instance de caractères de nom de fichier non imprimables et de caractères <tab> à être écrits en tant que caractère <point-marque> ('?'). Les implémentations peuvent fournir cette option par défaut si la sortie est destinée à un terminal. " Donc, par exemple, ls -Aq | wc -lcompter tous les fichiers / répertoires ou ls -qp | grep -c /uniquement les répertoires non masqués, etc.
don_crissti
Merci pour votre contribution. Changé -bpour -q.
Frax
7

Si vous savez que le répertoire en cours contient au moins un fichier non caché:

set -- *; echo "$#"

Ceci est évidemment généralisable à n'importe quel glob.

Dans un script, cela a pour effet parfois regrettable de remplacer les paramètres de position. Vous pouvez contourner ce problème en utilisant un sous-shell ou une fonction (version Bourne / POSIX) telle que:

count_words () {
  eval 'shift; '"$1"'=$#'
}
count_words number_of_files *
echo "There are $number_of_files non-dot files in the current directory"

Une solution alternative est $(ls -d -- * | wc -l). Si le glob est *, la commande peut être raccourcie à $(ls | wc -l). L'analyse de la sortie de lsme met toujours mal à l'aise, mais ici, cela devrait fonctionner tant que vos noms de fichiers ne contiennent pas de nouvelles lignes, ou que vous les lséchappiez. Et $(ls -d -- * 2>/dev/null | wc -l)a l'avantage de gérer le cas d'un glob ne correspondant pas (c'est-à-dire qu'il renvoie 0 dans ce cas, alors que la set *méthode nécessite un test fastidieux si le glob peut être vide).

Si les noms de fichier peuvent contenir des caractères de nouvelle ligne, une autre solution consiste à utiliser $(ls -d ./* | grep -c /).

Chacune de ces solutions reposant sur le transfert de l'extension d'un glob à lspeut échouer avec une erreur de liste d'arguments trop longue s'il y a beaucoup de fichiers correspondants.

Gilles
la source
1
Voulez-vous vraiment créer 13 923 paramètres de position? Et vous devriez faire votre variable locale localou l'éliminer: eval $1=$#ou simplement utiliser echo $#et faire number_of_files=$(count_words *).
Dennis Williamson
1
@ Dennis: une partie du but était d'éviter de fourrer. Je suppose que ce n'est pas une préoccupation du 21ème siècle. Ok, j’admets que je n’aime plus les shells non-POSIX, j’aurais donc pu éviter la variable temporaire.
Gilles
Pourquoi en avez-vous soustrait un $#(vous ne l'aviez pas fait avant le montage)?
Dennis Williamson
@Dennis: J'évite toujours un fork (enfin, cela fait une différence sur les machines avec un processeur lent tel que les routeurs) et passe un nom de variable comme $1. Donc, ce que je veux compter, c'est le nombre de paramètres qui ne sont pas le premier paramètre. (Je ne peux pas utiliser shiftparce que je dois garder le nom de la variable.) (Euh, si vous aviez posé des questions sur la première ligne ...)
Gilles
@ Dennis: à bien y penser, je peux l'utiliser shiftsi je le fais bien.
Gilles
7

J'ai trouvé du --inodesutile, mais je ne sais pas quelle version en dua besoin. Il devrait être considérablement plus rapide que les approches alternatives utilisant findet wc.

Sur Ubuntu 17.10, les travaux suivants:

du --inodes      # all files and subdirectories
du --inodes -s   # summary
du --inodes -d 2 # depth 2 at most

Combinez avec | sort -nrpour trier par ordre décroissant le nombre d'inodes contenus.

krlmlr
la source
5

En utilisant la paire ls / wc si nous ajoutons -U, cela sera beaucoup plus rapide (ne pas trier).

ls -AqU | wc -l
Jbnair
la source
1
-Uest spécifique à GNU cependant.
Stéphane Chazelas
4

Après avoir installé la commande tree, tapez simplement:

tree

Si vous voulez aussi des fichiers cachés:

tree -a

Si vous utilisez Debian / Mint / Ubuntu Linux, tapez la commande suivante pour installer la commande tree:

sudo apt-get install tree

L'option -L est utilisée pour spécifier le niveau d'affichage maximal de l'arborescence. La commande tree ne compte pas seulement le nombre de fichiers, mais également le nombre de répertoires, en prenant en compte autant de niveaux de l'arborescence que vous le souhaitez.

lev
la source
Lorsque je tape tree, j'obtiens une sorte d'arborescence à l'écran du répertoire dans lequel je me trouve, mais je ne vois pas où est indiqué le nombre de fichiers.
charlesdarwin
2
find -maxdepth 1 -type f -printf . | wc -c
  • -maxdepth 1le rendra non-récursif, findest récursif par défaut
  • -type f inclura les fichiers uniquement
  • -printf .est une touche mignonne. il imprime un point pour chaque fichier au lieu du nom de fichier, et est maintenant capable de gérer n'importe quel nom de fichier et enregistre également les données; il suffit de compter les points :)
  • | wc -c compte les personnages
aude
la source
1

Pas de tuyau, pas de copie de chaîne, pas de fourche, juste un liner

$ fcount() { local f i=0; for f in *; do let i++; done; echo $i; }; fcount
DaboD
la source
1
Donne une valeur de 1 si aucun fichier n'est dans le répertoire. Ne compte pas les fichiers, compte les fichiers et les répertoires.
Steve
1

Voici une autre technique dans le sens de celle que Gilles a postée :

word_count () { local c=("$@"); echo "${#c[@]}"; }
file_count=$(word_count *)

qui crée un tableau avec 13 923 éléments (si c'est le nombre de fichiers).

Dennis Williamson
la source
Quel est le point de ce ctableau? word_count() { echo "$#"; }serait suffisant. Le but de la solution @Gilles est de stocker le compte dans une variable renvoyée pour éviter de devoir utiliser la substitution de commande (qui implique un fork et un pipe dans des shells autres que ksh93).
Stéphane Chazelas
1
find . -type f -maxdepth 1 |  wc -l 

Cela ne peut lister que les fichiers du répertoire courant.

pappu
la source
find . -type ftrouvera des fichiers dans le répertoire en cours, et aussi, de manière récursive, dans des sous-répertoires.
Dhag
0

Essayez ceci j'espère que cette réponse vous aidera

echo $((`ls -l | wc -l` -1 ))
tigre
la source
0

Vous pouvez vérifier avec:

ls -l | grep -v ^l | wc -l
AMIC MING
la source
0

Améliorer certaines réponses données auparavant mais cette fois-ci explicitement.

$ tree -L 1 | tail -n 1 | cut -d " " -f 3

Il est digne de noter l'utilisation de commandes aimées comme tailet cut. Notez également que l’arborescence n’est pas disponible par défaut. La commande ci-dessus commence par capturer des informations sur le répertoire au niveau 1, puis affiche la dernière ligne tail -n 1où se trouve notre objectif et finit par cutprendre le troisième mot.

Par exemple, localiser dans /:

/ $ tree -L 1
.
├── 1
├── bin -> usr/bin
├── boot
├── dev
├── etc
├── home
├── lib -> usr/lib
├── lib64 -> usr/lib64
├── lost+found
├── media
├── mnt
├── opt
├── proc
├── root
├── run
├── sbin -> usr/sbin
├── srv
├── sys
├── tmp
├── usr
└── var

20 directories, 1 file
/ $ tree -L 1 | tail -n 1
20 directories, 1 file
/ $ tree -L 1 | tail -n 1 | cut -d " " -f 3
1

Alors, pourquoi ne pas demander le nombre de répertoires?

jonaprieto
la source
0

Sous Linux, pour rendre la commande très robuste et gérer les fichiers dont le nom peut contenir une nouvelle ligne, utilisez ceci:

find -maxdepth 1 -type f -print0 | tr -cd '\0' | wc -c

Cela nous évite l' épreuve de l'analyse de la lssortie.


Apparenté, relié, connexe:

codeforester
la source
-2

Utilisez la treecommande, juste:

tree
utilisateur115186
la source