Apparemment je ne peux pas compter. Je pense qu'il y a trois fichiers dans /media
$ tree /media
/media
├── foo
├── onex
└── zanna
3 directories, 0 files
Cependant, ls -l
en trouve 12.
$ ls -l /media
total 12
drwxr-xr-x 2 root root 4096 Jul 31 20:57 foo
drwxrwxr-x 2 root root 4096 Jun 26 06:36 onex
drwxr-x---+ 2 root root 4096 Aug 7 21:17 zanna
Et si je fais ls -la
, je n’obtiens que .
et ..
en plus de ce qui précède, mais le nombre est total 20
Quelle est l'explication?
Le 12
que vous voyez n’est pas le nombre de fichiers, mais le nombre de blocs de disque utilisés.
De info coreutils 'ls invocation'
:
For each directory that is listed, preface the files with a line
`total BLOCKS', where BLOCKS is the total disk allocation for all
files in that directory. The block size currently defaults to 1024
bytes, but this can be overridden (*note Block size::). The
BLOCKS computed counts each hard link separately; this is arguably
a deficiency.
Le total passe de 12
à 20
lorsque vous utilisez ls -la
au lieu de ls -l
car vous comptez deux répertoires supplémentaires: .
et ..
. Vous utilisez quatre blocs de disque pour chaque répertoire (vide), votre total va donc de 3 × 4 à 5 × 4. (Selon toute probabilité, vous utilisez n bloc de disque de 4096 octets pour chaque répertoire ; comme l'indique la page info
, l'utilitaire ne vérifie pas le format du disque, mais suppose une taille de bloc de 1024
, sauf indication contraire.)
Si vous voulez simplement obtenir le nombre de fichiers, vous pouvez essayer quelque chose comme:
ls | wc -l
ser4556274 a déjà répond le pourquoi . Ma réponse ne sert qu'à fournir des informations supplémentaires pour comment compter correctement les fichiers.
Dans la communauté Unix, le consensus général est que l’analyse de la sortie de ls
est une très très mauvaise idée , car les noms de fichiers peuvent contenir des caractères de contrôle ou des caractères cachés. Par exemple, en raison d'un caractère de nouvelle ligne dans un nom de fichier, ls | wc -l
nous dit qu'il y a 5 lignes dans la sortie de ls
(ce qui est le cas), mais en réalité il n'y a que 4 fichiers dans le répertoire.
$> touch FILE$'\n'NAME
$> ls
file1.txt file2.txt file3.txt FILE?NAME
$> ls | wc -l
5
La commande find
, qui est généralement utilisée pour analyser les noms de fichiers, peut nous aider ici en imprimant le numéro d'inode . Que ce soit un répertoire ou un fichier, il ne possède qu'un seul numéro d'inode. Ainsi, en utilisant -printf "%i\n"
et en excluant .
via -not -name "."
, nous pouvons avoir un décompte précis des fichiers. (Notez l'utilisation de -maxdepth 1
pour empêcher la descente récursive dans les sous-répertoires)
$> find -maxdepth 1 -not -name "." -print
./file2.txt
./file1.txt
./FILE?NAME
./file3.txt
$> find -maxdepth 1 -not -name "." -printf "%i\n" | wc -l
4
Manière simple, rapide et surtout portable:
$ set -- *
$ echo $#
228
La commande set
permet de définir les paramètres de position du shell (les variables $<INTEGER>
, comme dans echo $1
). Ceci est souvent utilisé pour contourner la limitation /bin/sh
des tableaux manquants. Une version qui effectue des vérifications supplémentaires peut être trouvée dans réponse de Gille sur Unix et Linux.
Dans les shells prenant en charge les tableaux, tels que bash
, nous pouvons utiliser
items=( dir/* )
echo ${#items[@]}
tel que proposé par steeldriver dans les commentaires .
Astuce similaire à la méthode find
qui utilisait wc
et globstar peut être utilisé avec stat
pour compter les numéros d'inode par ligne:
$> LC_ALL=C stat ./* --printf "%i\n" | wc -l
4
Une autre approche consiste à utiliser un caractère générique dans la boucle for
. (Notez que ce test utilise un répertoire différent pour vérifier si cette approche descend dans des sous-répertoires, ce qui n'est pas le cas - 16 correspond au nombre vérifié d'éléments dans mon ~/bin
.)
$> count=0; for item in ~/bin/* ; do count=$(($count+1)) ; echo $count ; done | tail -n 1
16
Python peut également traiter les noms de fichiers problématiques en imprimant la longueur d'une liste à l'aide de ma fonction os.listdir()
(non récursive et répertorie uniquement les éléments du répertoire indiqué en tant qu'argument).
$> python -c "import os ; print os.listdir('.')"
['file2.txt', 'file1.txt', 'FILE\nNAME', 'file3.txt']
$> python -c "import os ; print(len(os.listdir('.')))"
4