ディレクトリ全体のサイズを簡単に得るには?

[上に] [前に] [次に]
ふにゃちん 1999/12/17(金) 14:37:47
perlでサーバー上にある、指定のディレクトリ全体のサイズを簡単に得るのはどうしたらいいでしょうか?

opendirで、ディレクトリに入っているファイル名全てを取りだし、そのサイズ全てを合計するというやり方で出来ることは確認済みなのですが、ファイル数が多いときなど処理能力が不安なため、出来ることならもっと簡単に実現したいと思います。

ちなみに
perl の
(stat("ディレクトリ名"))[7]
や、
unixコマンドの
ls -l ディレクトリ名
で出力される値というのは、そのディレクトリに入っているファイル全部のサイズを合計したものにはなっていませんでした(この値にはどんな意味があるんでしょう?)。

PTAN 1999/12/17(金) 14:47:14
$hoge = `du -ks /dir/hogehoge`;
$dirsize = $& if ($hoge =~ /^\d+/);
確かめてはいませんが、こんな感じかな。

たぶん 1999/12/17(金) 14:59:27
>unixコマンドの
>ls -l ディレナt
ps ax
exit
su
exit
ps ax
exit
ps ax
last | more
cat /etc/hosts.allow
exit
ps ax
exit
su
exit
========================================
From: 三原克大
E-Mail: yunomegumi.mihara@nifty.com
Date: 2000/01/06(木) 11:08:33

# のどあめさんの二回目の投稿の内容が気にかかるのですが

気まぐれさんがおっしゃるように
まず CGI プログラムを起動させなければならないので、
サーバに CGI を使用する必要があると認識させなければなりません。
多くのサーバでは拡張子で判断していると思われますから、
URI を決めるときに CGI のための拡張子を選ぶか
サーバの設定を変えることになります。
後者は面倒くさかったり必要な権限がもらえなかったりするので
前者を選ぶことが多いでしょう。
すると、はた目には普通の CGI とそんなに変わらなかったりします。

CGI プログラム内での処理は、
気まぐれF = $& if ($hoge =~ /^\d+/);

/dir/hogehogeの部分をディレクトリ名にするんですよね?
試してみたしたが、なにも入りませんでした(泣)
--- ここまで

それから ls -l ディレクトリ名 のイメージは例えばこんな風になっています。

total 22
drwxr-xr-x  2 xxx      xxxxxx        512 Nov 10 09:26 ./
drwxrwxrwx 13 xxx      xxxxxx       1024 Dec 15 09:05 ../
-rw-rw-rw-  1 xxx      xxxxxx       1484 Oct 14 10:16 0.gif
-rw-rw-rw-  1 xxx      xxxxxx       1440 Oct 14 10:16 1.gif
-rw-rw-rw-  1 xxx      xxxxxx       1477 Oct 14 10:16 2.gif
-rw-rw-rw-  1 xxx      xxxxxx       1473 Oct 14 10:16 3.gif
-rw-rw-rw-  1 xxx      xxxxxx       1467 Oct 14 10:16 4.gif
-rw-rw-rw-  1 xxx      xxxxxx       1477 Oct 14 10:16 5.gif
-rw-rw-rw-  1 xxx      xxxxxx       1485 Oct 14 10:16 6.gif
-rw-rw-rw-  1 xxx      xxxxxx       1447 Oct 14 10:16 7.gif
-rw-rw-rw-  1 xxx      xxxxxx       1499 Oct 14 10:16 8.gif
-rw-rw-rw-  1 xxx      xxxxxx       1496 Oct 14 10:16 9.gif

ファイル名「./」のところに示されている「512」というのが、(stat(ディレクトリ名))[7]で所得できます。でもそれは「0.gif」〜「9.gif」のサイズを合計したものとは違う値です。

ふにゃちん 1999/12/17(金) 16:57:08
↑また、おかしくなっちゃったみたい・・・・・

きたむら 1999/12/17(金) 18:26:37
statやlsコマンドで得られるサイズは、ディレクトリ(という特殊なファイル)自身のサイズです。たとえば、unixコマンドの
% hd ディレクトリ名
を実行すると、ディレクトリ自身の内容がダンプ表示されますが、それが何バイト使ってるかってことです。

本題のサイズ合計のほうは、PTANさんの方法以上にいい案が浮かびませんです。
duコマンドをフルパス(/usr/bin/du等)で指定してみたらどうでしょうか。

ふにゃちん 1999/12/17(金) 18:38:15
$hoge = `/usr/bin/du -ks ディレクトリ名`;
$dirsize = $& if ($hoge =~ /^\d+/);
print "$dirsize<P>\n";

duコマンドをフルパスで実行してみましたが(/usr/bin/duが存在することはチェック済)、やはり何も入ってきませんでした。

ただ、Telnetで
du -ks ディレクトリ名
を実行すると、

du: illegal option -- k
Usage: du [-as] file . . .

というエラーメッセージが出力されたので、そもそも「-k」というオプションはないのでは? と思われます。

ちなみに、「du -ks」を「du -s」でやってみると、上記ディレクトリの場合、「21」と出力されました(これまた、ファイルサイズ合計の値と違う! なぜ??)

PTAN 1999/12/18(土) 13:49:26
とすると、21*512=10752バイトではないでしょうか?
Solaris,LINUX等では通常は512バイト単位、-kオプション
によりキロバイト単位になります。

B-Cus 1999/12/18(土) 14:11:37
> ファイル数が多いときなど処理能力が不安なため
結局足を引っ張るのは、perl じゃなくてディスク入出力じゃないかね。
du でも perl でも、速度はあまり変わらないと思う。
# 試してないけど。


ちなみに、File モジュールを使うやり方はこんな感じ。

use File::Find;
use File::stat;
finddepth(\&wanted, '/foo/bar/');
print "total=$total\n";

sub wanted {
    if ( ! -f $_ ){
        print "SKIP $_\n";
        next;
    }
    $size = stat($_)->size;
    print "$_ $size\n";
    $total += $size;
}

きたむら 1999/12/19(日) 18:31:23
># 試してないけど。
さっそく試してみました。FreeBSD 3.3R+Perl 5.005_03(日本語patch4)

#!/usr/local/bin/perl
require 'stat.pl';
use Benchmark;
delete $ENV{'BLOCKSIZE'};

foreach $dir ('dir10', 'dir180') {
  print "------- $dir\n";
  print "size_du=", &size_du, "\n";
  print "size_stat=", &size_stat, "\n";
  timethese(500, {
    'du' => '&size_du',
    'stat' => '&size_stat',
  });
}

sub size_du {
  return `du -s $dir` - (stat($dir))[$ST_BLOCKS];
}

sub size_stat {
  local $blocks, $entry;
  opendir(DIR, $dir);
  while ($entry = readdir(DIR)) {
    if (-f "$dir/$entry") {
      $blocks += (stat(_))[$ST_BLOCKS];
    }
  }
  return $blocks;
}

ディレクトリdir10には10個、dir180には180個のファイルが入っています。
結果は以下のようになりました(表示サイズはブロック単位で512倍がバイト数)

------- dir10
size_du=36
size_stat=36
Benchmark: timing 500 iterations of du, stat...
  du: 5 wallclock secs ( 0.17 usr  0.24 sys +  1.50 cusr  3.01 csys =  0.00 CPU)
stat: 1 wallclock secs ( 0.66 usr +  0.53 sys =  1.19 CPU)
------- dir180
size_du=432
size_stat=432
Benchmark: timing 500 iterations of du, stat...
  du: 10 wallclock secs ( 0.20 usr  0.23 sys +  2.84 cusr  6.28 csys =  0.00 CPU)
stat: 17 wallclock secs (12.05 usr +  4.67 sys = 16.72 CPU)

ファイル数が少ないときは、duコマンドのオーバーヘッドが目立ちますが、
ファイル数が多いと、それなりにduコマンドが効果を発揮します。

#もちろんOSやduコマンドの実装の違いなども関係するでしょうから、これは一例ってことで…。
##それにしても、Benchmarkモジュールって便利ですねー。

ふにゃちん 1999/12/19(日) 23:45:11
[[解決]]
# とりあえず、このスレッドはこのハンドルで・・・

みなさま、ありがとうございました。
とくにきたむらさん、わざわざベンチマークテストまでやっていただいて、ありがとうございます。

ファイル数によって、実行時間に差が発生するようですね。
まだ、これを利用する「あて」が具体的にあるわけではないですが、その時が来ましたら、ファイル数がどのくらいになるか予測を立てた上でどちらを使うか決定したいと思います。
ありがとうございました。

[上に] [前に] [次に]