Nombre d'octets de «ls -l <fichier aléatoire>» par rapport à «wc -c <fichier aléatoire>»

25

Y a-t-il une situation possible lorsque

ls -l file.txt

affiche pas le même nombre d'octets que

wc -c file.txt

Dans un script, j'ai trouvé une comparaison de ces deux valeurs. Quelle pourrait être la raison de cela? Est-il même possible d'avoir différents nombres d'octets du même fichier?

Rokas.ma
la source
2
Pourriez-vous donner un peu de contexte à ce script que vous avez trouvé?
Kusalananda
Voir aussi unix.stackexchange.com/a/321502/22565
Stéphane Chazelas

Réponses:

13

Oui, il y a de tels cas.

En cas de liens symboliques sur un système Linux avec GNU ls, le ls -laffichera la taille du lien, tandis que wc -crésoudra le fichier réel et y lira le nombre d'octets. Ci-dessous, vous pouvez voir que ls -lrapporte 29 octets, alors que wc172 rapporte dans le fichier réel.

$ ls -l /etc/resolv.conf                                                                                                 
lrwxrwxrwx 1 root root 29 1月  17  2016 /etc/resolv.conf -> ../run/resolvconf/resolv.conf
$ wc -c /etc/resolv.conf                                                                                                 
172 /etc/resolv.conf
$ wc -c /var/run/resolvconf/resolv.conf                                                                                  
172 /var/run/resolvconf/resolv.conf
$ ls -l /var/run/resolvconf/resolv.conf                                                                                  
-rw-r--r-- 1 root root 172 1月  15 15:49 /var/run/resolvconf/resolv.conf

Dans le cas de systèmes de fichiers virtuels , tels que/proc ou /sys, de nombreux fichiers s'affichent comme ayant une taille 0 ls -l. Sous le /devsystème de fichiers, nous avons une variété de fichiers spéciaux, tels que les périphériques de caractères et les périphériques de bloc - se wc -cbloque sur ceux-ci et ls -laffiche des nombres majeurs et mineurs au lieu de la taille.

Les canaux nommés seront signalés en 0octets par ls -c, mais wc -cliront en fait le contenu du canal, donc techniquement, il vous indiquera la quantité de données dans le canal nommé:

$ mkfifo named.pipe                                                                                                      
$ echo "This is a test" > named.pipe &
[1] 2129
$ ls -l named.pipe
prw-rw-r-- 1 xieerqi xieerqi 0 1月  16 08:40 named.pipe|
$ wc -c named.pipe
15 named.pipe
[1] + Done                 echo "This is a test" >named.pipe 

Pour un fichier normal, la taille doit être égale.


Le point de ls -let wc -c, et leur fonctionnement diffèrent également. wc -couvre réellement le fichier pour la lecture (vous pouvez le voir si vous exécutez strace wc -c /etc/passwdpar exemple). ls -leffectue uniquement l' stat()appel sur ceux-ci. Cela explique également pourquoi, dans la /proc ls -ltaille 0, vous ne pouvez pas statiser ces fichiers car ils ne sont pas "réels" ou réellement stockés sur le disque dur / ssd.wc -cà la place, lit le contenu de ce fichier et calcule sa taille.

Finalement, ls -l n'est qu'un outil pour répertorier les éléments de manière interactive. C'est rarement un bon choix pour les scripts. Lorsque vous avez réellement besoin de lire les données, utilisez wc -cplutôt.

Veuillez noter que pour l'écriture de scripts et l'évaluation de la taille d'un fichier, ce lsn'est pas le meilleur candidat. En fait, c'est l'une des pratiques courantes pour éviter l'analyse de la lssortie . Veuillez utiliser du -b pour connaître la taille d'un fichier.

Sergiy Kolodyazhnyy
la source
1
Une petite précision - fichiers virtuels (en /sys/, /proc/etc.) peut fournir des statinformations, si les Implementer choisit de. La plupart du temps, il n'y a pas de raison impérieuse, donc c'est omis. Les exemples incluent /proc/kcorece qui est rapporté comme la taille de la mémoire du noyau adressable (généralement beaucoup plus que la mémoire physique disponible).
Toby Speight
11

ls -l renverra la taille du fichier signalé par le système de fichiers.

wc -ctentera de lire le fichier pour déterminer la taille «réelle». D'après mes observations, il semble d'abord essayer de chercher jusqu'à la fin, et si cela ne fonctionne pas, il lira le fichier entier, en comptant la taille au fur et à mesure.

Il s'agit d'une simple description de ce que font les deux outils, mais elle entraîne un certain nombre d'implications pour les résultats:

lsdonnera une sortie incorrecte pour certains systèmes de fichiers. Par exemple, les systèmes de fichiers virtualisés comme /procrapporteront une taille nulle pour de nombreux fichiers, car ces "fichiers" ne sont physiquement stockés nulle part; ils sont générés selon les besoins du logiciel.

wcne fonctionnera pas du tout pour les fichiers sans autorisations de lecture, alors qu'il lsne nécessite que des autorisations pour répertorier le répertoire (comparer ls -l /etc/shadowà wc -c /etc/shadow).

Comme mentionné dans d'autres réponses, le comportement des liens symboliques est également différent. Parce qu'il wcessaie de les lire, il finit par lire le fichier vers lequel pointe le lien symbolique, tandis que parce lsqu'il interroge simplement le système de fichiers, il indiquera la taille utilisée pour stocker le lien symbolique lui-même.

Je suis sûr qu'il y a d'autres différences auxquelles je n'ai pas encore pensé, mais je pensais donner une explication claire et simple quant à la raison fondamentale derrière ces différences.

Muzer
la source
+1 pour avoir mentionné les autorisations de lecture et seek(). Cela semble être le cas, après avoir exécuté strace wc -lquelques gros fichiers.
Sergiy Kolodyazhnyy
+1 pour avoir ajouté beaucoup plus de détails que ma réponse!
Cyclic3
6

Pour un fichier normal, ls et wc appellent stat. Cependant, pour un fichier de / proc ou / sys, ls renvoie 0, mais wc renvoie un nombre différent:

$ ls -l /proc/modules
-r--r--r--  1 root root 0 Jan 16 14:56 modules
                        ^ this one
$ wc -c /proc/modules
7621 modules

C'est probablement un moyen de savoir si quelque chose est un fichier spécial.

Cyclic3
la source
2
wc -cpour moi au moins appelle fstat, mais apparemment à d'autres fins. Il trouve la longueur du fichier lseekjusqu'à la fin. Dans le cas où cela renvoie une erreur, il s'agit de readl'intégralité du fichier.
Muzer