千字节到人类可读。寻找一个班轮
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【讨论】:
我希望它看起来像 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
【讨论】:
以上是关于千字节到人类可读。寻找一个班轮的主要内容,如果未能解决你的问题,请参考以下文章