千字节到人类可读。寻找一个班轮

Posted

技术标签:

【中文标题】千字节到人类可读。寻找一个班轮【英文标题】:kilobytes to human readable. Looking for one liner 【发布时间】:2011-12-12 18:21:10 【问题描述】:

我经常在没有 du 的 -h 标志的 unix 机器上工作。

我正在寻找一种将 KB 转换为人类可读的单行器。 Perl 似乎是一个不错的选择。 这是我目前所拥有的。

@a=split /\s+/;
$x=$_!=0?int(log()/log(1024)):0;
@b=('K','M','G');
printf("%.3s%s\t%s\n",$_/(1024)**$x,$b[$x],$a[1]);

像这样运行:

du -ks * | perl -lne '@a=split /\s+/;$x=$_!=0?int(log()/log(1024)):0;@b=('K','M','G');printf("%.3s%s\t%s\n",$_/(1024)**$x,$b[$x],$a[1]);'

由于我无法找到正确的 printf 格式,它无法完美运行。

使用 perl 以及 awk/sed 等的单行代码将是最有用的。

这就是 du -h 的样子。最多 1 个小数。最小值:0 位小数。带四舍五入。

8.0K
1.7M
4.0M
5.7M
88K

更新:

du -ks * | perl -lane '$F[0];$x=$_!=?int(log()/log(1024)):0;printf("%.3s%s\t%s\n",$_/1024**$x,qw<K M G>[$x],$F[1]);'

【问题讨论】:

好提示。我将在一秒钟内更新 OP。 经过一番研究,看起来这不能只用一个标准的 printf 说明符来完成;参看。 prthumanval 在 the Mac OS X implementation of du 中,根据要显示的数字是否大于 10,有不同的情况。 您在更新后的 oneliner 中缺少 0,应该是 "$_ != 0", 【参考方案1】:

这使用来自 CPAN 的 Number::Bytes::Human

du -ks * |perl -MNumber::Bytes::Human=format_bytes -nle \
    '@F=split(/\s+/,$_,2); printf("%-10s%s\n", format_bytes($F[0]*1024), $F[1])'

编辑:不使用模块:

du -ks * |perl -nle \
   '@F=split(/\s+/,$_,2); $b=$F[0]*1024; for($i=0;$b>1024;$i++)$b/=1024 $u=qwB K M G T[$i]; printf("%10.".($b=~/\./?1:0)."f$u  %s\n", $b, $F[1])'

【讨论】:

好主意,但遗憾的是:'无法在 @INC 中找到 Number/Bytes/Human.pm'。另外,对带有空格的文件进行很好的思考。 @user606723:对,它不是核心 Perl 安装的一部分。您需要从 CPAN 下载它。 @user606723 - 好吧,如果您安装了该模块,那么您可以根据需要多次使用该衬垫。这就是模块背后的主要思想之一:高度可重用的代码。 @user606723 - 完全可行:search.cpan.org/~apeiron/local-lib-1.008004/lib/local/lib.pm 和/或search.cpan.org/~gugod/App-perlbrew-0.30/lib/App/perlbrew.pm 如果您无法安装 CPAN 模块,那么您就没有充分利用 Perl 的强大功能。至于在 20 多个主机上安装它 - 为什么不使用 puppet 之类的东西?【参考方案2】:

你正确的 printf() 格式:

sub get_filesize_str

    my $file = shift;

    my $size = (stat($file))[7] || die "stat($file): $!\n";

    if ($size > 1099511627776)    #   TiB: 1024 GiB
        return sprintf("%.2f TiB", $size / 1099511627776);
     elsif ($size > 1073741824)  #   GiB: 1024 MiB
        return sprintf("%.2f GiB", $size / 1073741824);
     elsif ($size > 1048576)     #   MiB: 1024 KiB
        return sprintf("%.2f MiB", $size / 1048576);
     elsif ($size > 1024)        #   KiB: 1024 B
        return sprintf("%.2f KiB", $size / 1024);
     else                        #   bytes
        return sprintf("%.2f bytes", $size);
    

这不是我的代码,取自here

【讨论】:

我已经试过了.. 它在所有内容的末尾填充 .00.. 这有点烦人。 你可以随时通过s/\.00$//. 最好是制作一个包含逻辑和描述的 perl 脚本,而不是用一条丑陋的线来做所有事情:) @user973254,通常是的,但在这种情况下能够更好地传输脚本我的副本和粘贴。有太多的框和太多的登录名,无法将其移动到每个人... %.0f 也不起作用,因为它们将没有小数位。用示例更新了操作。【参考方案3】:
du -sk * | perl -ane '
  $i=0;
  while ($F[0]>1024) $F[0]/=1024; $i++; 
  printf("%d%s\t%s\n", $F[0], qw(K M G)[$i], $F[1])
'

如果你想要更大数字的分数:

du -sk * | perl -ane '
  $i=0;
  while ($F[0]>1024) $F[0]/=1024; $i++;;
  $f = $i==0 ? "d" : ".2f"; 
  printf("%$f%s\t%s\n", $F[0], qw(K M G)[$i], $F[1])
'

【讨论】:

【参考方案4】:

如果您想要进行的唯一修改(不清楚您想要什么)是让数字在 3 个字符的字段中右对齐,只需从 printf 格式中删除句点即可。此外,与其显式调用split 并将整个$_ 视为一个数字,我建议将-a 开关传递给Perl,它会自动将空格上的$_ 拆分为数组@F,然后替换在您的代码中使用$F[0] 引用$_

因此,您的代码可以重写(使用更多 Perlisms 并添加一些空格以提高可读性):

杜 -ks * | perl -lane '$x = $F[0] != 0 && int(log($F[0])/log(1024)); printf("%3d%s\t%s\n", $F[0]/1024**$x, qw[$x], $F[1]);'

【讨论】:

我希望它看起来像 du -hs *。此外,我们使用 %s 的方式,它只是截断字符,它不会舍入或其他任何东西。 如果$F[1] 中的文件名有空格/制表符怎么办?【参考方案5】:

这是改编自***上的一些答案的AWK函数:

function human_readable(sum) 

hum[1024**3]="GiB";hum[1024**2]="MiB";hum[1024]="KiB"; 
    for (x=1024**3; x>=1024; x/=1024) 
        if (sum>=x)  v = sprintf( "%.2f %s",sum/x,hum[x]); return v 
    

【讨论】:

以上是关于千字节到人类可读。寻找一个班轮的主要内容,如果未能解决你的问题,请参考以下文章

从gzip文件到python中文本的字节

javascript 人类可读的字节数

python 人类可读字节转换

PHP 使字节化人类可读

csharp 用于以人类可读方式表示任意字节长度的实用程序。

将人类可读的文件大小转换为 ruby​​ 中的字节