Это старый вопрос, и на него уже правильно ответили, но на случай, если ваша программа ограничена основными модулями, и вы не можете использовать Number :: Bytes :: Human здесь у вас есть несколько других варианты у меня были собраны со временем. Я сохранил их также потому, что каждый из них использует свой подход Perl и является хорошим примером для TIMTOWTDI :
- пример 1: использует состояние, чтобы избежать повторной инициализации переменной каждый раз (перед perl 5.16 вам нужно использовать состояние объекта или perl -E)
http://kba49.wordpress.com/2013/02/17/format-file-sizes-human-readable-in-perl/
sub formatSize {
my $size = shift;
my $exp = 0;
state $units = [qw(B KB MB GB TB PB)];
for (@$units) {
last if $size < 1024;
$size /= 1024;
$exp++;
}
return wantarray ? ($size, $units->[$exp]) : sprintf("%.2f %s", $size, $units->[$exp]);
}
- пример 2: использование карты сортировки
.
sub scaledbytes {
# http://www.perlmonks.org/?node_id=378580
(sort { length $a <=> length $b
} map { sprintf '%.3g%s', $_[0]/1024**$_->[1], $_->[0]
}[" bytes"=>0]
,[KB=>1]
,[MB=>2]
,[GB=>3]
,[TB=>4]
,[PB=>5]
,[EB=>6]
)[0]
}
- пример 3: Воспользуйтесь преимуществом того факта, что 1 Гб = 1024 Мб, 1 Мб = 1024 Кб и 1024 = 2 ** 10:
.
# http://www.perlmonks.org/?node_id=378544
my $kb = 1024 * 1024; # set to 1 Gb
my $mb = $kb >> 10;
my $gb = $mb >> 10;
print "$kb kb = $mb mb = $gb gb\n";
__END__
1048576 kb = 1024 mb = 1 gb
- пример 4: использование
++$n and ... until ..
для получения индекса для массива
.
# http://www.perlmonks.org/?node_id=378542
#! perl -slw
use strict;
sub scaleIt {
my( $size, $n ) =( shift, 0 );
++$n and $size /= 1024 until $size < 1024;
return sprintf "%.2f %s",
$size, ( qw[ bytes KB MB GB ] )[ $n ];
}
my $size = -s $ARGV[ 0 ];
print "$ARGV[ 0 ]: ", scaleIt $size;
Даже если вы не можете использовать Number :: Bytes :: Human, взгляните на исходный код, чтобы увидеть все, что вам нужно знать.