J'essaie de trouver la taille des fichiers sur mon disque dur en octets exacts, mais chaque fois que la taille devient trop grande, le nombre devient étrange (comme 1.98329e + 12). Puis-je l'empêcher de le faire ou le convertir en octets exacts?
La commande est:
ls -lR | grep -v '^d' | awk '{total += $5} END {print "Total:", total}'
Image d'octets exacts:
Image de nombre étrange:
du -sb
affiche correctement les octets, quelle que soit la taille du répertoire.ntfs
alors j’ai essayé de les formater en ext4 et de les copier. Les résultats sont les mêmes que ntfs.Le problème est que MAWK (la variante AWK installée sur Ubuntu) imprime par défaut des entiers supérieurs à 2147483647
(231-1) en notation scientifique:
% awk -W version
mawk 1.3.3 Nov 1996, Copyright (C) Michael D. Brennan
compiled limits:
max NF 32767
sprintf buffer 2040
% printf '2147483647\n' | awk '{x += $1; print x}'
2147483647
% printf '2147483648\n' | awk '{x += $1; print x}'
2.14748e+09
Vous pouvez utiliser printf
avec un spécificateur de format au lieu de print
*:
printf '2147483648\n' | awk '{x += $1; printf "%.0f\n", x}'
% printf '2147483648\n' | awk '{x += $1; printf "%.0f\n", x}'
2147483648
Dans ton cas:
ls -lR | grep -v '^d' | awk '{total += $5} END {printf "Total:%.0f\n", total}'
ls -lR |
grep -v '^d' |
awk '
{
total += $5
}
END {
printf "Total:%.0f\n", total
}
'
Cela forcera AWK à imprimer total
en notation décimale au lieu de notation scientifique.
Cependant, sur une autre note, vous ne devriez jamais analyser ls
.
Une méthode plus sensible consiste à utiliser find
+ stat
:
find . -type f -exec stat -c '%s' {} + | awk '{total += $1} END {printf "Total:%.0f\n", total}'
find . -type f -exec stat -c '%s' {} + |
awk '
{
total += $1
}
END {
printf "Total:%.0f\n", total
}
'
* %.0f
est une astuce pour créer printf
des nombres plus grands que 2147483647
(231-1), qui, lorsque vous utilisez %d
en tant que spécificateur de format, sera toujours imprimé en tant que 2147483647
. La limite de %.0f
est que l’on commence à perdre de la précision après 9007199254740992
(253), si cela vous pose un problème (merci à Rotsor pour les informations utiles).
TL; DR: ls
et awk
ne sont pas nécessaires pour vous. Utilisez du -cb
ou du -bs
sur le répertoire que vous souhaitez analyser.
Votre but est de
Toutes ces actions peuvent être effectuées par du
.
$ du -bs $HOME 2>/dev/null
76709521942 /home/xieerqi
Il est intéressant de noter que du
a deux "modes" - il peut indiquer combien de fichiers ont une taille OR combien d’espace disque réel qu’ils occupent (la réalité, la réalité physique). Puisque vous êtes intéressé par la taille totale de tous les fichiers, vous voulez la taille apparente du fichier. L'indicateur -b
indique exactement que (-b
est l'alias de --apparent-size --block-size=1
).
Une solution encore plus concise et appropriée serait peut-être d’utiliser du -bc
directement sur le répertoire de votre choix. Par exemple, mon répertoire personnel fait environ 76 Go.
$ du -bc $HOME 2> /dev/null | tail -1
76694582570 total
Pour une raison quelconque, vous vous inquiétez de la différence de taille de dossier et de taille de fichier. Vous avez dit dans les commentaires:
Je préférerais ls car la taille des répertoires varie lorsque la taille des fichiers est constante
du
est récursif et résume la taille des fichiers. De plus, un répertoire a une taille statique de 4096 octets (4k), mais avec du
, il sera inclus dans le résultat de du -bs directory_name
. Considère ceci:
$ du -b suse/openSUSE-Leap-42.1-DVD-x86_64.iso
4648337408 suse/openSUSE-Leap-42.1-DVD-x86_64.iso
$ du -b suse/
4648341504 suse/
$ bc <<< "4648337408+4096"
4648341504
$ mkdir suse/another_dir
$ du -b suse/another_dir
4096 suse/another_dir
$ du -bs suse/
4648345600 suse/
Sous le capot, awk
effectue tous les calculs en utilisant des nombres à virgule flottante en double précision. Par défaut, il les imprime avec printf(3)
spécificateur de format %.6g
, ce qui signifie que si le nombre comporte plus de six chiffres, il basculera sur E-notation , c'est ce que vous avez vu. Vous pouvez contourner ce problème en définissant la variable OFMT
:
ls -lR |
awk 'BEGIN { OFMT = "%d" }
/^-/ { total += $5 }
END { print "Total:", total }'
Mais il existe une limite supérieure, au-delà de laquelle il ne peut pas vous donner un nombre exact d'octets; il commencera à arrondir les bits bas de la somme. 500 gigaoctets = 500 * 1024 * 1024 * 1024 = 536870912000 239. Avec la virgule flottante IEEE habituelle, celle-ci est bien en dessous de cette limite (qui est approximativement 252). Cependant, il est suffisamment grand pour que je me sente personnellement mieux à utiliser un langage de programmation doté de "bignums" appropriés (entiers de taille illimitée). Par exemple, Python:
#! /usr/bin/python
import os
import sys
space = 0L # L means "long" - not necessary in Python 3
for subdir, dirs, files in os.walk(sys.argv[1]):
for f in files:
space += os.lstat(os.path.join(subdir, f)).st_size
sys.stdout.write("Total: {:d}\n".format(space))
Ceci est également totalement immunisé contre les problèmes de fichiers contenant des caractères inhabituels dans leurs noms. Et il compte l'espace utilisé par les fichiers cachés.
Ceci calcule le nombre d'octets visibles dans chaque fichier , ce qui correspond à ce que ls -l
imprime. Si vous voulez le nombre d'octets réellement occupés sur le disque à la place (ce que du
imprime), remplacez .st_size
par .st_blocks * 512
. (Oui, le multiplicateur est toujours 512, même si st_blksize
est un nombre différent.)
Ce que vous voyez ici est un moyen d’afficher de grands nombres. Par exemple:
1.23e+3 = 1.23*10^3 = 1230
Autant que je sache, vous ne pouvez pas désactiver cela, mais comme vous l'avez écrit dans votre question, du
se comporte différemment, je vous recommande donc de l'utiliser. Sinon, vous devrez convertir les chiffres.