Ce que 12vous voyez n'est pas le nombre de fichiers, mais le nombre de blocs de disques consommé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 va de 12à 20lorsque vous utilisez à la ls -laplace de ls -lcar vous comptez deux répertoires supplémentaires: .et ... Vous utilisez quatre blocs de disque pour chaque répertoire (vide), votre total passe donc de 3 × 4 à 5 × 4. (Selon toute vraisemblance, vous utilisez un bloc de disque de 4096 octets pour chaque répertoire; comme l' infoindique la page, le l'utilitaire ne vérifie pas le format du disque, mais suppose une taille de bloc de, 1024sauf indication contraire.)
Si vous voulez simplement obtenir le nombre de fichiers, vous pouvez essayer quelque chose comme
ls | wc -léchouera s'il y a des fichiers avec une nouvelle ligne dans le nom de fichier. C'est plus résistant:find . -mindepth 1 -maxdepth 1 -printf . | wc -c
Flimm
20
"si les noms de fichiers contiennent une nouvelle ligne" ... frémissement
Petah
8
Comme man lsvous le direz, vous pouvez éviter les caractères de contrôle avec -b(les échappe) ou -q(les omet). Donc, pour le comptage, ls -1q | wc -lest sûr et précis pour afficher des fichiers non cachés. ls -1qA | wc -lpour compter les fichiers cachés (mais pas .et ..). J'utilise -1au lieu de -lcar cela devrait être plus rapide.
Oli
18
user4556274 a déjà répondu au pourquoi . Ma réponse ne sert qu'à fournir des informations supplémentaires sur la façon de compter correctement les fichiers.
Dans la communauté Unix, le consensus général est que l' analyse de la sortie de lsest 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, nous avons ls | wc -ldit qu'il y a 5 lignes dans la sortie de ls(ce qu'il a), 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
Méthode # 1: trouver l'utilitaire
La findcommande, qui est généralement utilisée pour contourner les noms de fichiers, peut nous aider ici en imprimant le numéro d'inode . Qu'il s'agisse d'un répertoire ou d'un fichier, il n'a qu'un seul numéro d'inode unique. 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 1pour empêcher la descente récursive dans les sous-répertoires)
setLa commande est utilisée pour définir les paramètres positionnels du shell (les $<INTEGER>variables, comme dans echo $1). Ceci est souvent utilisé pour contourner la /bin/shlimitation des tableaux manquants. Une version qui effectue des vérifications supplémentaires peut être trouvée dans la réponse de Gille sur Unix et Linux.
Dans les shells qui prennent en charge les tableaux, tels que bash, nous pouvons utiliser
Astuce similaire à la findméthode utilisée wcet globstar peut être utilisé avec statpour 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 en forboucle. (Remarque, ce test utilise un répertoire différent pour tester si cette approche descend dans les sous-répertoires, ce qu'elle ne fait pas - 16 est le nombre vérifié d'éléments dans my ~/bin)
$> count=0; for item in ~/bin/* ; do count=$(($count+1)) ; echo $count ; done | tail -n 1
16
Méthode n ° 3: autres langues / interprètes
Python peut également traiter les noms de fichiers problématiques en imprimant la longueur d'une liste étant donné ma os.listdir()fonction (qui est non récursive, et ne listera que les éléments du répertoire donnés en 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
En bash, une autre option serait d'utiliser un tableau par exemple items=( dir/* ); echo ${#items[@]}(en ajoutant shopt -s dotglobpour inclure des fichiers cachés).
steeldriver
1
L'impression de numéros d'inode facilite le filtrage des liens physiques si vous le souhaitez, avec find | sort -u | wc -l.
Peter Cordes
@steeldriver: Je pense que la méthode bash-array ne sera probablement pas plus rapide. Si vous voulez qu'il soit récursif, vous devez utiliser items=( dir/** )(avec shopt -s globstar), mais bash ne tire pas parti des métadonnées supplémentaires de readdir, il analyse donc chaque entrée de répertoire pour voir s'il s'agit d'un répertoire lui-même. De nombreux systèmes de fichiers stockent le type de fichier dans l'entrée de répertoire, donc readdir peut le renvoyer sans accéder aux inodes. (Par exemple, le dernier XFS non par défaut a cela, et je pense que ext4 l'a depuis plus longtemps.) Si vous stracetrouvez, vous verrez beaucoup moins d' statappels système que stracing bash.
Peter Cordes
2
Pourquoi ne pas simplement utiliser print(len(os.listdir('.')))? Moins de caractères à taper et évite également d'accéder aux attributs doublement soulignés.
ls | wc -l
échouera s'il y a des fichiers avec une nouvelle ligne dans le nom de fichier. C'est plus résistant:find . -mindepth 1 -maxdepth 1 -printf . | wc -c
man ls
vous le direz, vous pouvez éviter les caractères de contrôle avec-b
(les échappe) ou-q
(les omet). Donc, pour le comptage,ls -1q | wc -l
est sûr et précis pour afficher des fichiers non cachés.ls -1qA | wc -l
pour compter les fichiers cachés (mais pas.
et..
). J'utilise-1
au lieu de-l
car cela devrait être plus rapide.user4556274 a déjà répondu au pourquoi . Ma réponse ne sert qu'à fournir des informations supplémentaires sur la façon de 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, nous avonsls | wc -l
dit qu'il y a 5 lignes dans la sortie dels
(ce qu'il a), mais en réalité il n'y a que 4 fichiers dans le répertoire.Méthode # 1: trouver l'utilitaire
La
find
commande, qui est généralement utilisée pour contourner les noms de fichiers, peut nous aider ici en imprimant le numéro d'inode . Qu'il s'agisse d'un répertoire ou d'un fichier, il n'a qu'un seul numéro d'inode unique. 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)Méthode n ° 2: globstar
Manière simple, rapide et surtout portable:
set
La commande est utilisée pour définir les paramètres positionnels du shell (les$<INTEGER>
variables, comme dansecho $1
). Ceci est souvent utilisé pour contourner la/bin/sh
limitation des tableaux manquants. Une version qui effectue des vérifications supplémentaires peut être trouvée dans la réponse de Gille sur Unix et Linux.Dans les shells qui prennent en charge les tableaux, tels que
bash
, nous pouvons utilisercomme proposé par Steeldriver dans les commentaires .
Astuce similaire à la
find
méthode utiliséewc
et globstar peut être utilisé avecstat
pour compter les numéros d'inode par ligne:Une autre approche consiste à utiliser un caractère générique en
for
boucle. (Remarque, ce test utilise un répertoire différent pour tester si cette approche descend dans les sous-répertoires, ce qu'elle ne fait pas - 16 est le nombre vérifié d'éléments dans my~/bin
)Méthode n ° 3: autres langues / interprètes
Python peut également traiter les noms de fichiers problématiques en imprimant la longueur d'une liste étant donné ma
os.listdir()
fonction (qui est non récursive, et ne listera que les éléments du répertoire donnés en argument).Voir également
la source
items=( dir/* ); echo ${#items[@]}
(en ajoutantshopt -s dotglob
pour inclure des fichiers cachés).find | sort -u | wc -l
.items=( dir/** )
(avecshopt -s globstar
), mais bash ne tire pas parti des métadonnées supplémentaires de readdir, il analyse donc chaque entrée de répertoire pour voir s'il s'agit d'un répertoire lui-même. De nombreux systèmes de fichiers stockent le type de fichier dans l'entrée de répertoire, donc readdir peut le renvoyer sans accéder aux inodes. (Par exemple, le dernier XFS non par défaut a cela, et je pense que ext4 l'a depuis plus longtemps.) Si vousstrace
trouvez, vous verrez beaucoup moins d'stat
appels système que stracing bash.print(len(os.listdir('.')))
? Moins de caractères à taper et évite également d'accéder aux attributs doublement soulignés.