Я пытаюсь найти размер файлов на моем жестком диске в точных байтах, но каждый раз, когда размер становится слишком большим, число становится все странным (как 1.98329e+12). Я могу мешать ему делать это или преобразовать это в точные байты?
Команда:
ls -lR | grep -v '^d' | awk '{total += $5} END {print "Total:", total}'
Изображение точных байтов:
Изображение странного числа:
du -sb
правильно точные байты шоу, неважно, насколько большой каталог.ntfs
таким образом, я пытался форматировать тот как ext4 и скопировать мои файлы. Результаты - то же как ntfs.Проблема состоит в том, что MAWK (вариант AWK установил на Ubuntu) целыми числами печати по умолчанию, больше, чем 2147483647
(231-1) в экспоненциальном представлении:
% 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
Вы могли использовать printf
с форматом specifer вместо print
*:
printf '2147483648\n' | awk '{x += $1; printf "%.0f\n", x}'
% printf '2147483648\n' | awk '{x += $1; printf "%.0f\n", x}'
2147483648
В Вашем случае:
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
}
'
Это вынудит AWK распечатать total
в десятичной записи вместо в экспоненциальном представлении.
Однако на другой ноте, Вы никогда не должны анализировать ls
.
Более чувствительный способ сделать, который использовал бы 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
прием должен сделать printf
числа печати, больше, чем 2147483647
(231-1), который при использовании %d
поскольку спецификатор формата всегда печатал бы как 2147483647
. Предел %.0f
тот, начнет терять точность после 9007199254740992
(253), если это - когда-нибудь беспокойство (благодаря Rotsor для полезной информации).
TL; DR: ls
и awk
являются ненужными для Вашей цели. Использовать du -cb
или du -bs
на каталоге, который Вы хотите проанализировать.
Ваша цель к
Все эти действия могут быть выполнены du
.
$ du -bs $HOME 2>/dev/null
76709521942 /home/xieerqi
Стоит заметить это du
имеет два "режима" - это может или показать, сколько файла находится в размере ИЛИ сколько пространства фактической дисковой емкости это поднимает (настоящий, физический агент по операциям с недвижимостью). Так как Вы интересуетесь общим размером всех файлов, Вы хотите очевидный размер файла. -b
флаг дает точно это ( -b
псевдоним для --apparent-size --block-size=1
).
Возможно, еще более краткое и соответствующее решение состояло бы в том, чтобы использовать du -bc
непосредственно на каталоге Вы хотите. Например, мой корневой каталог составляет приблизительно 76 ГБ в размере
$ du -bc $HOME 2> /dev/null | tail -1
76694582570 total
По некоторым причинам Вы волнуетесь о разнице в размерах папки и размере файла. Вы сказали в комментариях:
Я предпочел бы ls, потому что размеры каталога варьируются, в то время как размеры файла являются постоянными
du
является рекурсивным, и подводит итог размеров файла. Кроме того, каталог действительно имеет статический размер 4 096 байтов (4k), но с du
это будет включено в результат du -bs directory_name
. Рассмотрите это:
$ 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/
Под капотом, awk
делает все вычисления с помощью чисел с плавающей точкой двойной точности. По умолчанию это печатает их использование printf(3)
спецификатор формата %.6g
, что означает, что, если число является больше чем шестью цифрами, широкими, оно переключится на электронную нотацию, которая является тем, что Вы видели. Можно работать вокруг этого путем установки переменной OFMT
:
ls -lR |
awk 'BEGIN { OFMT = "%d" }
/^-/ { total += $5 }
END { print "Total:", total }'
Но существует верхний предел, вне которого это не может дать Вам точное число байтов; это начнет округлять младшие биты суммы. 500 гигабайтов = 500 * 1024 * 1024 * 1024 = 536870912000 ≈ 239. С обычной плавающей точкой IEEE это безопасно ниже того предела (который является примерно 252). Однако это является достаточно большим, что я лично чувствовал бы себя лучше с помощью языка программирования, который имел надлежащие "сверхбольшие числа" (целые числа неограниченного размера). Например, 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))
Это также абсолютно неуязвимо для проблем с файлами с необычными символами на их имена. И это считает пространство использованным скрытыми файлами.
Это вычисляет число байтов, видимых в каждом файле, который совпадает со что ls -l
печать. Если Вы хотите число байтов, на самом деле занял на диске вместо этого (что du
печать), замена .st_size
с .st_blocks * 512
. (Да, множитель всегда 512, даже если st_blksize
другое число.)
Что Вы видите, вот способ отобразить большие количества. Например:
1.23e+3 = 1.23*10^3 = 1230
Насколько я знаю, Вы не можете выключить это, но как Вы записали в своем вопросе, du
действительно ведет себя по-другому, таким образом, я рекомендовал бы использовать это. Иначе необходимо было бы преобразовать числа.