可读格式的文件大小

给定一个文件的大小(以字节为单位) ,我想将其格式化为 < a href = “ https://en.wikipedia.org/wiki/Binary _ prefix”rel = “ noReferrer”> IEC (二进制)前缀 3 < a href = “ http://en.wikipedia.org/wiki/ignant _ figure”rel = “ noReferrer”> 有意义的数字 后面带零,例如,1883954变成1.80 M。

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

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

编辑: 这里还有一个问题。请看下面 Adrian Frühwirth 的评论。

78777 次浏览

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

你为什么不用

ls -lh

指挥官?如果您使用的是最近几年发布的 Linux 系统,那么您就具有这种功能。

如果你碰巧安装了 计算!(顺便说一句,这个很棒) , 有个小窍门:

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

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

GNU Coreutils 包含一个名为 numfmt的小工具,用于数字转换,它可以满足您的需要:

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

我认为这非常适合你的需要,而且不像其他答案那样庞大或骇客。

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

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

我知道现在有点晚了,但是希望有人能帮上忙。

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


测试:

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

使用 stat -c %s filename.ext代替使用 lsawk获取文件大小。它只输出数字,没有其他内容(至少在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