给定文件的大小(以字节为单位),我想用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'}
不使用ls
和awk
来获取文件大小,而是使用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
如果你想要一个更简单,更轻的解决方案,看看我的另一个答案。