人类可读格式的文件大小



给定文件的大小(以字节为单位),我想用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

(文件没有那么大,所以我不需要考虑更大的单位)

编辑:这还有一个问题。

你为什么不使用

ls -lh

命令吗?如果您使用的是最近几年发布的Linux系统,则可以使用此功能。

GNU coretils包含一个明显不为人知的用于数字转换的小工具numfmt,它可以满足您的需要:

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

我认为这个答案很符合你的需要,而且不像其他答案那么大或粗俗。

如果你想要一个更强大的解决方案,看看我的另一个答案。

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

不使用lsawk来获取文件大小,而是使用stat -c %s filename.ext。它只输出数字,不输出其他内容(至少在8.21版本上)。我不能使用numfmt,因为它是一个较旧的版本,似乎没有使用十进制精度的printf语法。我使用下面的脚本。我使用最后一行来测试脚本是否被引用。如果不是,我可以直接在命令行上调用它。

#!/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

我知道有点晚了。但也许有人会发现它有用。

答案很简单,在脚本中使用%.2f而不是%.3g。(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

如果您不介意使用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

如果你碰巧有Qalculate!安装(顺便说一下,这是很棒的),有一个简单的技巧:

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

的例子:

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

在shell脚本中,它是一个非常非常强大的工具,因为它甚至可以简化公式,解决未知问题,以及更多的事情。

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

如果你想要一个更简单,更轻的解决方案,看看我的另一个答案。

最新更新