Размер файла в человекообразном формате - программирование
Подтвердить что ты не робот

Размер файла в человекообразном формате

Учитывая размер файла в байтах, я хочу отформатировать его с префиксами IEC (двоичными) до 3 значащих цифр с конечными нулями, например, 1883954 становится 1,80M.

Арифметика с плавающей точкой не поддерживается в bash, поэтому вместо нее я использовал awk. Проблема в том, что я не умею держать конечные нули. Текущее решение:

if [ $size -ge 1048576 ]
then
    size=$(awk 'BEGIN {printf "%.3g",'$size'/1048576}')M
elif [ $size -ge 1024 ]
then
    size=$(awk 'BEGIN {printf "%.3g",'$size'/1024}')K
fi

(Файлы не такие большие, поэтому мне не нужно рассматривать большие единицы.)

Изменение: Есть еще одна проблема с этим. См. Комментарий Адриана Фрювирта ниже.

4b9b3361

Ответ 1

GNU Coreutils содержит, по-видимому, довольно неизвестный небольшой инструмент numfmt для преобразования numfmt, который делает то, что вам нужно:

$ numfmt --to=iec-i --suffix=B --format="%.3f" 4953205820
4.614GiB

Я думаю, что это хорошо соответствует вашим потребностям, и не так велико или хакерски, как другие ответы.

Если вы хотите более мощное решение, посмотрите на мой другой ответ.

Ответ 2

Есть ли причина, по которой вы не используете

ls -lh

команда? Если вы находитесь в системе Linux, выпущенной за последние несколько лет, у вас есть эта функция.

Ответ 3

ls -lah /path/to/your/file | awk -F " " {'print $5'}

Ответ 4

Я знаю, что это немного поздно. Но может кто-то сочтет это полезным.

Ответ заключается в том, чтобы просто использовать %.2f вместо %.3g в script. (src)


Тест:

#!/bin/bash

size=1883954

if [ $size -ge 1048576 ]
then
    size=$(awk 'BEGIN {printf "%.2f",'$size'/1048576}')M
elif [ $size -ge 1024 ]
then
    size=$(awk 'BEGIN {printf "%.2f",'$size'/1024}')K
fi

echo $size

Выход:

1.80M

Ответ 5

Если вы не против использования bc, то следующие операции будут выполнять операции с плавающей запятой. scale может изменяться в соответствии с вашими потребностями в зависимости от многих цифр, которые вы хотите распечатать.

size=1883954

if [ $size -ge 1048576 ]
then
    size=$(echo "scale=2;$size/1048576"| bc)M
elif [ $size -ge 1024 ]
then
    size=$(echo "scale=2;$size/1024" | bc)K
fi

echo $size

Ответ 6

Вместо того, чтобы использовать ls и awk для получения размера файла, используйте stat -c %s filename.ext. Он выводит только номер, и ничего больше (по крайней мере, на версии 8.21). Я не могу использовать numfmt, потому что это более старая версия, которая не использует синтаксис printf с десятичной точностью. Вместо этого я использую script ниже. Я использую последнюю строку для проверки наличия источника script. Если это не так, я могу вызвать его непосредственно в командной строке.

#!/bin/bash

function getFriendlyFileSize() {
    OUT='/dev/null'
    [ "$#" == 0 ] && echo 'No number given' && return 1
    [ ! $(echo $1 | egrep -i '\-?[0-9]+') ] && echo 'Garbage data' && return 1

    if [ "$1" == '' -o "$1" -lt 0 ] 2>$OUT
    then
            echo '0 B'
            return 1
    else
            FSIZE=$1
    fi

    [ "$2" == '' ] && DECPTS=1 || DECPTS=$2

    KB=1024
    MB=1048576
    GB=1073741824
    TB=1099511627776
    PB=1125899906842624
    EB=1152921504606846976
    LM=9223372036854775807 # bash comparison limit = 2^63-1 (signed int?)

    [ "$FSIZE" -le 0 ] 2>$OUT && echo "0 B" && return
    [ "$FSIZE" -lt $KB ] 2>$OUT && echo "$FSIZE B" && return
    [ "$FSIZE" -lt $MB ] 2>$OUT && echo "$(echo "scale=$DECPTS;$FSIZE/$KB"|bc) KB" && return
    [ "$FSIZE" -lt $GB ] 2>$OUT && echo "$(echo "scale=$DECPTS;$FSIZE/$MB"|bc) MB" && return
    [ "$FSIZE" -lt $TB ] 2>$OUT && echo "$(echo "scale=$DECPTS;$FSIZE/$GB"|bc) GB" && return
    [ "$FSIZE" -lt $PB ] 2>$OUT && echo "$(echo "scale=$DECPTS;$FSIZE/$TB"|bc) TB" && return
    [ "$FSIZE" -lt $EB ] 2>$OUT && echo "$(echo "scale=$DECPTS;$FSIZE/$PB"|bc) PB" && return
    [ "$FSIZE" -le $LM ] 2>$OUT && echo "$(echo "scale=$DECPTS;$FSIZE/$EB"|bc) EB" && return
    [ "$?" -ne '0' ] 2>$OUT && echo "Bad input" && return 1
}

[[ $_ == $0 ]] && getFriendlyFileSize $1 $2

Ответ 7

Если у вас установлено Qalculate! (что, кстати, удивительно) Theres легкий трюк:

human_readable="$( qalc -t set "precision $precision" "${in_bytes}B" )"

Пример:

$ qalc -t -set "precision 3" 5264334820B
5.26 GB

Это очень мощный инструмент для работы с оболочками, поскольку он даже упрощает формулы, решает для неизвестных и многое другое.

$ qalc -t "e^(i*x)=-1"
x = 3.1415927

Если вы хотите более простое и менее тяжелое решение, посмотрите на мой другой ответ.

Ответ 8

Предпочтительное решение

man stat

* Пример использования " читабельного формата " в stat: *

stat %A custom_file.txt

ура