【问题标题】:Why do du and Perl's -s give different values for the file size?为什么 du 和 Perl 的 -s 为文件大小提供不同的值?
【发布时间】:2010-09-22 19:44:43
【问题描述】:

根据 cmets 更新:

我有 outlog.txt 文件,其中包含多个文件名,例如:2345_535_Dell&HP_3PAR_DEAL.txt,同样有许多文件名,但不是文件所在的实际文件夹,因此在代码中将文件名附加到文件夹路径以获取实际文件位置。现在,我想获取outlog.txt 中所有文件的磁盘使用情况以及outlog.txt 中所有文件的总磁盘使用情况。

我尝试了两种方法 perl -s 和 my ($size) = split(' ', du `"$folderpath/$_"`) 但两种方法都给了我不同的值,而且当我使用 @987654327 时@ 比我得到一些数值,但它没有给我单位,有没有一种方法可以让我在不使用 -h 选项的情况下获得人类可读性,因为它在我的系统上不起作用?

背景信息

我的目标是获取文件的大小,目前我正在使用perl -s 来获取文件大小。我也尝试过du,并且得到了同一文件大小的不同值。我无法理解这是如何工作的。

问:为什么duperl -s 给出不同的大小值?它们在内部是如何工作的?这两个不同的值中哪一个更准确?另外,我不知道为什么du -h filename 给我一个非法表达式错误:

bash-2.03$ du -h test.txt
/usr/bin/du: illegal option -- h
usage: du [-a][-d][-k][-r][-o|-s][-L] [file ...]

代码:

my $folderpath = 'the_path';
open my $IN, '<', 'path/to/infile';
my $total;
while (<$IN>) {
    chomp;
    my $size = -s "$folderpath/$_";
    print "$_ => $size\n";
    $total += $size;
}
print "Total => $total\n";

礼貌:RickF

更新:

问: 如何获取每个文件的磁盘使用值而不是文件大小,这意味着如何获取每个文件的 du 值而不是 perl -s 文件的值?

操作系统信息 名称:SunOS uname -v :Generic_117350-39

更新代码:根据大脑的方法,但 du 值仍然打印为零而不是实际值,有什么建议吗?

更新: 如果我使用我的 ($size) = split(' ', du "$folderpath/$_");比我得到 du 的价值,但它给了我一些数字,我怎样才能在不使用 -h 选项的情况下将它变成人类可读的?

 #!/usr/bin/perl
 use strict;
 use warnings;

my $folderpath = '/Project/upload';
open my $IN, '<', 'outlog.txt';
my $total;
while (<$IN>) {
    chomp;
    #my( $block_size, $blocks ) = ( stat( "$_" ) )[11,12];
    #my $du_size = $block_size * $blocks;
    my ($size) = split(' ', `du "$folderpath/$_"); 
    #my $size = -s "$folderpath/$_";
    print "$_ => $size\n";
    $total += $size;
}
print "Total => $total\n";

【问题讨论】:

    标签: perl file unix storage command


    【解决方案1】:

    du 报告实际磁盘使用情况,Perl 的-s 报告文件大小。因此,如果一个文件是 4 字节长,它将有 4 字节的大小,但磁盘使用量为 4 KB(取决于您的文件系统的设置方式)。

    您还会看到sparse files 的大小有所不同。稀疏文件占用的空间比它们声称的要少。

    【讨论】:

      【解决方案2】:

      默认情况下,du 显示文件使用的块数(在大多数系统上每个块为 512 字节),而 perl 的 -s 显示字节数。

      至于为什么您的du 副本没有-h 选项,您没有告诉我们您使用的是什么操作系统;它似乎包含一个非常过时的程序版本。

      更新:要在 perl 中获取磁盘使用情况,您可以使用 Filesys::DiskUsage 模块。

      【讨论】:

      • @Wooble - 我没有为Filesys::DiskUsage 安装.pm
      • @Rachel, cpanp install Filesys::DiskUsage
      • @Evan: 是这个命令吗,其实我还处于Perl 的早期阶段,所以不太熟悉以智能方式执行perl :0
      • @Rachel Yep,对于 5.10+ 使用 cpanp,该命令将为您完成所有工作。
      • @Rachel:您还应该cpanp install autodieuse autodie;(您没有在代码中检查$!
      【解决方案3】:

      du 代表“Disk Used”,报告磁盘上文件的物理大小。如果文件是稀疏的,这可能比它的逻辑大小小得多,这是-s 报告的。两者都是“准确的”,它们只是测量不同的东西。

      错误信息表明您机器上安装的du版本不理解-h选项。

      【讨论】:

      • 鉴于Wooble's,我发现此响应令人困惑,如果du 显示blocks(512 bytes),则该数字为更小是因为一个 block 可以容纳 512 个 bytes,而不是因为文件是 sparse?除非我错过了什么。
      • @Evan Carroll, du 能够以不同的单位报告尺寸。我不确定 SunOS 的默认单位是什么。试试man du
      【解决方案4】:

      如果您希望 du 提供与 Perl 的 -s 相同的结果,请尝试 du -b。如果您的du 支持它,这会给出“表观大小”,这与其他人所说的磁盘使用情况不同。

      但要做到这一点,您必须更新您的du

      更新 OP 的更新代码:确保该文件存在于您当前的工作目录中。您可能需要预先添加目录以确保 Perl 正在查找该文件。

      如果您避免在任何地方使用$_,它也可能会澄清一些事情:

      while( my $line = <$IN> ) {
        chomp $line;
        my( $block_size, $blocks ) = ( stat( $line ) )[11,12];
        ...
      }
      

      这样您就可以避免无意更改$_

      【讨论】:

      • 埃文,defined 不是必需的。当我们到达文件末尾时,&lt;$IN&gt; 返回undef,它被分配给$line。因此,赋值的返回值也是undef,它被转换为false,while() 循环退出。这就是我回滚添加defined 检查的编辑的原因。
      • @CanSpice 这是必要的,如果你得到一个名为 0 或 " " 的文件,你将停止执行(并不是说它真的发生太多,但你让你的结果依赖于perl 真值表,而不是 eof())
      • @Ether:你是对的,但是 Perl 文档具有误导性。他们说,“如果且仅当输入符号是while语句的条件中唯一的东西” - 但后来通过显示while (my $line = &lt;STDIN&gt;)也表现出与“且仅当”部分相矛盾以同样的方式。让我们想知道这个 DWIMmery 将在哪些情况下执行。
      • @j_random:谢谢;我们可以在 perldocs 的下一个版本中澄清这一点。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-07
      • 2021-12-23
      • 2019-03-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多