关于linux:人类可读格式的文件大小

File size in human readable format

考虑到文件的字节大小,我想用IEC(二进制)前缀将其格式化为3个带尾随零的有效数字,例如1883954变为1.80米。

bash不支持浮点运算,所以我使用了awk。问题是我不知道如何保持尾随零。当前解决方案:

1
2
3
4
5
6
7
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

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

编辑:还有一个问题。请参见下面的Adrian Fr_hwirth评论。


你有什么理由不使用

1
ls -lh

命令?如果您使用的是Linux系统,该系统在过去几年中已经发布,那么您就具有此功能。


GNU coreutils包含一个显然相当未知的小工具,叫做numfmt,用于数字转换,它可以满足您的需要:

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

我认为这很适合你的需要,而且没有其他答案那么大或那么刻薄。

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


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


我知道有点晚了。但希望有人发现它有用。

答案很简单,就是在脚本中使用%.2f而不是%.3g。(SRC)

测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/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
1.80M


如果您不介意使用bc,那么下面的内容将有助于执行浮点运算。scale可以根据您的需要进行更改,具体取决于您要打印的数字。

1
2
3
4
5
6
7
8
9
10
11
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


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#!/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


如果你碰巧有计算!安装(顺便说一句,太棒了)有一个简单的诀窍:

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

例子:

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

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

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

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