Comment puis-je obtenir la taille d'un fichier en mégaoctets en utilisant Perl?

je veux obtenir la taille d'un fichier sur disque en mégaoctets. À l'aide de la -s l'opérateur me donne la taille en octets, mais je vais supposer que diviser ceci par un nombre magique est une mauvaise idée:

my $size_in_mb = (-s $fh) / (1024 * 1024);

devrais-je utiliser une variable en lecture seule pour définir 1024 ou y a-t-il un moyen programmatique pour obtenir la quantité d'octets dans un kilo-octet?

EDIT: mise à jour du calcul incorrect.

13
demandé sur Perleone 2009-02-04 18:18:14

8 réponses

si vous voulez éviter les nombres magiques, essayez le module CPAN Numéro: Octets::Homme.

use Number::Bytes::Human qw(format_bytes);
my $size = format_bytes(-s $file); # 4.5M
30
répondu jrockway 2009-02-04 18:25:22

vous pouvez bien sûr créer une fonction pour calculer ceci. C'est une meilleure solution que de créer des constantes dans cette instance.

sub size_in_mb {
    my $size_in_bytes = shift;
    return $size_in_bytes / (1024 * 1024);
}

Pas besoin de constantes. Modification de l' 1024 à une variable / constante quelconque ne rendra pas ce code plus lisible.

6
répondu Peter Stuifzand 2009-02-05 16:18:18

Eh bien, il n'y a pas 1024 octets dans un meg, il y a 1024 octets dans un K, et 1024 K dans un meg...

cela dit, 1024 est un nombre "magique" sûr qui ne changera jamais dans aucun système dans lequel vous pouvez vous attendre à ce que votre programme fonctionne.

4
répondu user54650 2009-02-04 15:19:44

je voudrais lire cela dans une variable plutôt que d'utiliser un nombre magique. Même si les nombres magiques ne vont pas changer, comme le nombre d'octets dans un mégaoctet, utiliser une constante bien nommée est une bonne pratique parce qu'elle rend votre code plus lisible. Il rend immédiatement évident pour tout le monde ce que votre intention est.

4
répondu Doug R 2009-02-04 15:34:03

il s'agit d'une question ancienne qui a déjà reçu une réponse correcte, mais juste au cas où votre programme est limité aux modules de base et que vous ne pouvez pas utiliser Numéro: Octets::Homme ici vous avez plusieurs autres options que j'ai été collectées au fil du temps. Je les ai gardé aussi parce que chacun utilise une approche Perl différente et est un bel exemple pour TIMTOWTDI:

  • exemple 1: utilise l'État pour éviter de réinitialiser la variable à chaque fois (avant perl 5.16 vous devez utiliser l'état de fonctionnalité ou 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]);
    }
  • exemple 2: Utilisation de la carte de tri

.

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]
  }
  • exemple 3: Profitez du fait que 1 Go = 1024 Mb, 1 Mo = 1024 Kb et 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
  • exemple 4: utilisation de ++$n and ... until .. pour obtenir un indice pour le tableau

.

# 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;  

même si vous ne pouvez pas utiliser Number::Bytes::Human, jetez un oeil au code source pour voir toutes les choses que vous devez être conscient de.

4
répondu Pablo Marin-Garcia 2014-03-16 10:00:40

1) vous ne voulez pas 1024. Qui vous donne kilo-octets. Vous voulez 1024*1024, ou 1048576.

2) Pourquoi diviser par un nombre magique serait une mauvaise idée? C'est pas comme si le nombre d'octets d'un mégaoctet allait changer. Ne pas overthink trop de choses.

1
répondu Chris Lutz 2009-02-04 15:20:51

Ne m'obtenez pas le mal, mais: je pense que la déclaration de 1024 comme une Magie Variable va un peu trop loin, c'est un peu comme "$UN = 1; $DEUX = 2;" etc.

un kilo-octet a été faussement déclaré comme 1024 octets depuis plus de 20 ans, et je doute sérieusement que les fabricants de système d'exploitation ne corrigeront jamais ce bug et le changeront à 1000.

ce qui pourrait avoir du sens c'est de déclarer des choses non évidentes, comme "$ megaoctet = 1024 * 1024 " puisque c'est plus lisible que 1048576.

1
répondu Michael Stum 2009-02-04 15:21:57

puisque l'opérateur-s renvoie la taille du fichier en octets, vous devriez probablement faire quelque chose comme

my $size_in_mb = (-s $fh) / (1024 * 1024);

et utiliser int() si vous avez besoin d'un chiffre rond. Ce n'est pas comme si les dimensions de KB ou MB allaient changer n'importe quand dans un futur proche :)

1
répondu aks 2009-02-04 15:26:07