【问题标题】:File size in human readable format人类可读格式的文件大小
【发布时间】:2013-04-06 18:10:27
【问题描述】:

考虑到文件的大小(以字节为单位),我想将其格式化为 IEC (binary) prefixes3 significant figures 并带有尾随零,例如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

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

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

【问题讨论】:

  • 这有点hack,但你能不能不转换成字符串,检查小数点后的长度,必要时加零?
  • GNU ls 命令接受-lh 选项...
  • @Basile Starynkevitch:不是我想要的格式。 3 平方英尺尾随零。
  • 假设您的 elif 文件大小为 1048575,您确定要此输出吗? $ echo "1048575" | awk '{ printf "%.3gK\n", $1/1024 }' => 1.02e+03K.
  • @Adrian Frühwirth:该死的我忘了。我最初使用 SI 单位,这不会有问题,但我决定更传统(这是用于索引文件)。

标签: linux bash


【解决方案1】:

你有什么理由不使用

ls -lh

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

【讨论】:

  • 因为它没有给出我想要的格式。就像我说的,到 3 个有效数字,尾随零。我给出的例子——1883954——用ls会变成1.8M,不是吗? (它可能与实现有所不同,但我的系统就是这样。)
  • 从中解析尺寸是一个严重的混乱。不要那样做!
  • 这是完美的答案。
  • @xtheking:我知道这对很多人来说是“完美答案”,但实际上并没有回答我的问题。正如 Evi1M4ahine 所提到的,它也有它的问题。诚然,如此广泛地命名这个问题是我的错。不过,我决定保留它,以便人们仍然可以找到这样的答案。
  • 根据这个答案(不是 OP 问题)ls -lh ~/.bashrc | cut -d ' ' -f 5 >> 101k
【解决方案2】:

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

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

我认为这很适合您的需求,并且不像其他答案那么大或笨拙。

如果您想要更强大的解决方案,请查看我的其他答案。

【讨论】:

  • 对不起,我以为它遵循 printf 格式。您能否更改它,以便将结果打印为三个有效数字,尾随零?否则我不能接受它作为答案。
  • 您可以从 8.24 版本开始指定精度。 numfmt --to=iec-i --suffix=B --format="%.3f" 4953205820 输出 4.614GiB
  • @project:如果您不想在前缀中使用 'i',而不是 --to=iec-i 选项,请使用 --to=iec
  • 有没有办法在数字和单位之间放置一个空格。例如 5 KB 而不是 5KB
  • @Tim:不幸的是,它看起来并不存在。您可以将输出通过管道传输到 sed:... | sed -r 's/([A-Z])/ \1/'.
【解决方案3】:
ls -lah /path/to/your/file | awk -F " " {'print $5'}

【讨论】:

  • 这种方法很好。不需要任何 3rd 方命令。
  • 出于好奇,如果您在一个文件夹中有很多文件(即 > 250,000),打电话给ls 会不会有很大的损失?
【解决方案4】:

不要使用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

【讨论】:

    【解决方案5】:

    我知道有点晚了。但可能有人会觉得它有用。

    答案很简单,就是在脚本中使用%.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
    

    【讨论】:

      【解决方案6】:

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

      【讨论】:

        【解决方案7】:

        如果你碰巧安装了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
        

        如果您想要一个更简单、重量更轻的解决方案,请查看我的其他答案。

        【讨论】:

          猜你喜欢
          • 2013-02-17
          • 2020-03-10
          • 1970-01-01
          • 2010-11-08
          • 2017-01-28
          • 2017-08-09
          • 1970-01-01
          • 2014-10-16
          • 2013-02-06
          相关资源
          最近更新 更多