以前各サブディレクトリの更新時間を取得するスクリプトを


<?php
function dirmtime($path, $level=3)
{
$mtime = filemtime($path);
if (0 < $level--) {
foreach (glob($path."/*") as $file) {
if (is_dir($file)) {
$subtime = dirmtime($file, $level);
if ($mtime < $subtime) {
$mtime = $subtime;
// echo $level.' '.$file.' '.date(DATE_RFC822, $mtime)."<br>";
} } } }
return $mtime;
}
?>
ご教示いただきましてそれを使っております。この時間を各ディレクトリごとに収集してそのもっとも最近の値を計算し、それと現在時刻の差を表示させればいいと思います。どのようにすればよいでしょうか。

回答の条件
  • 1人2回まで
  • 登録:
  • 終了:2010/04/13 11:10:03
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

回答2件)

id:Bombastus No.1

回答回数409ベストアンサー獲得回数52

ポイント35pt

以下のような感じでしょうか。

関数dhhmmssは表示用に使っているだけです。

<?php
function dhhmmss($t) {
    $d = (int)($t / (24 * 60 * 60));
    $h = (int)(($t - $d * 24 * 60 * 60) / (60 * 60));
    $m = (int)(($t - $d * 24 * 60 * 60 - $h * 60 * 60) / 60);
    $s = (int)(($t - $d * 24 * 60 * 60 - $h * 60 * 60) - $m * 60);
    return sprintf('%04d-%02d:%02d:%02d', $d, $h, $m, $s);
}

function difmtime($path, $level=3) {
    $now = time();
    $mtime = filemtime($path);
    $dtime = $now - $mtime;
    if (0 < $level--) {
        foreach (glob($path . "/*") as $file) {
            if (is_dir($file)) {
                $subtime = dirmtime($file, $level);
                if ($dtime > $subtime) {
                    $dtime = $subtime;
                    // printf("(%02d) %s %s<br />\n", $level, dhhmmss($dtime), $file);
                }
            }
        }
    }
    return $dtime;
}

$dtime = fidmtime(最初のディレクトリ);
echo '最新のものは ' . dhhmmss($dtime);
?>
id:tobeoscontinue No.2

回答回数220ベストアンサー獲得回数59

ポイント35pt

Aディレクトリーの中にB,C,Dのサブディレクトリーがあった時、dirmtime()はA,B,C,Dの更新日時を取得していました。

それが問題だったかもしれません。それとglob()はGLOB_ONLYDIRオプションを付けるとディレクトリーだけ拾得できるようなので書き直してみました。

またglob()は名前の先頭がドットのものは拾わないようです。それが問題ならreaddir()を使うようにする必要があるでしょう

<?php
function dirmtime($path, $myself = FALSE, $level=3)
{
  $mtime = ($myself) ? filemtime($path) : 0;
  if (0 < $level--) {
    foreach (glob($path."/*", GLOB_ONLYDIR) as $dir) {
      $subtime = dirmtime($dir, TRUE, $level);
      if ($mtime < $subtime) {
//      echo $level.' '.$dir.' '.date(DATE_RFC822, $mtime)." >> ".date(DATE_RFC822, $subtime)."\n";
        $mtime = $subtime;
  } } }
  return $mtime;
}

dirmtime("A")のようにするとAディレクトリーの中にあるB,C,Dのサブディレクトリーだけの更新日時を調べます。

dirmtime("A", TRUE)のようにするとAディレクトリー、B,C,Dのサブディレクトリーの更新日時を調べます(Aも含む)。


>各ディレクトリごとに収集して

<?php
function globr($path, $myself = FALSE, $level=3)
{
  $globr = ($myself) ? array($path) : array();
  if (0 < $level--)
    foreach (glob($path."/*", GLOB_ONLYDIR) as $path)
      $globr = array_merge($globr, globr($path, TRUE, $level));
  return $globr;
}

各ディレクトリのパスを配列に入れて返します。


>そのもっとも最近の値を計算し、

<?php
function globmtime($glob)
{
  $mtime = 0;
  foreach ($glob as $path) {
    $submtime = filemtime($path);
    if ($mtime < $submtime) {
      $mtime = $submtime;
      echo elapse(time()-$mtime).' '.date(DATE_RFC822, $mtime).' '.$path."\n";	//"<br>";
  } }
  return $mtime;
}

$globは各ディレクトリのパスが配列入ったとします。foreachで各ディレクトリのパスについてfilemtime($path)で更新日時を取得します。

最近の値とは一番大きい値ということなので現在の一番大きい値($mtime)より大きかったら入れ替えます。

echoは動作確認なので注釈か削除して下さい。


>それと現在時刻の差を表示させればいいと思います。

<?php
function elapse($time)
{
  $elp = array();
  foreach (array(''=>86400, ''=>3600, ''=>60, ''=>1) as $name=>$value) {
    if ($time > $value) {
      $u = intval($time / $value);
      $time -= $u*$value;
      $elp[] = $u.$name;
  } }
  return implode($elp,' ');
}

echo elapse(time()-globmtime(globr("対象ディレクトリ")));

elapse()は時刻の差を判りやすくするためだけのものです。

globr("対象ディレクトリ")で対象ディレクトリ内にあるサブディレクトリのパスを列挙した配列(対象ディレクトリは含まない)を入手し、globmtime()は各ディレクトリのパスから更新日時を調べて最新のものを返します。現在時刻はtime()で取得できますからこれとの差を取った値をelapse()で表示しています。


サブディレクトリの更新日時とそのサブディレクトリ内のファイルの更新日時とは必ずしも同期しません。

よってhttp://q.hatena.ne.jp/1270872723にあるような”最後にアップロードしてから31分です”というような目的には使えないと思います。

例えばディレクトリAにあるファイルを削除すればディレクトリAの更新日時は更新されます。それはもはや”最後にアップロード”された日時ではありません。

ファイルの更新日時を知るのであればhttp://q.hatena.ne.jp/1270519639にあるgetHighestFileTimestamp('対象ディレクトリ')を使うのが正しいでしょう。

ただパスの最後が/で終わってないとサブディレクトリは検索できないでしょう。

getHighestFileTimestamp('hoge')ではなくgetHighestFileTimestamp('hoge/')とする必要があります。

id:webster2

ありがとうございます。そうすると最終的にコードはどうなりますでしょうか。

2010/04/10 20:45:01
  • id:tobeoscontinue
    http://q.hatena.ne.jp/1269586208
    にあるように
    ディレクトリAの下にA1,A2,A3,...があり、A1,A2,A3,..にファイルをアップロードしたとして
    echo "最後にアップロードしてから".intval((time() - getHighestFileTimestamp('A/')) / 60)."分です";
    としてみてはどうでしょう。
  • id:rouge_2008
    http://jp.php.net/manual/ja/function.filemtime.php#91665

    上記のgetAllFiles関数とgetHighestFileTimestamp関数の他に、Bombastusさんが回答したdhhmmss関数を使用してはいかがでしょうか?
    ※dhhmmss関数は、http://q.hatena.ne.jp/1270872723#c176407にある変更を加えた物を使用します。

    関数の実行とブラウザへの表示は以下のようにします。

    $ntime = time() - getHighestFileTimestamp('./対象のトップフォルダ名/');
    echo "最終更新時刻は ". $dhhmmss($ntime) ."前です。";

    //以下は更新時刻も表示したい場合
    echo "【". date('Y/m/d H:i:s', getHighestFileTimestamp('./対象のトップフォルダ名/')) ."】<br>\n";
  • id:webster2
    function difmtime($path, $level=3)で計算した$dtimeは使わないということでしょうか?
  • id:rouge_2008
    > function difmtime($path, $level=3)で計算した$dtimeは使わないということでしょうか?


    はい、使用しません。
    「getHighestFileTimestamp('./対象のトップフォルダ名/')」を実行すると、対象のフォルダ内(サブフォルダ含む)のすべてのファイルのタイムスタンプを計算して、最新のファイルのタイムスタンプを返します。
    現在時刻「time()」から、「getHighestFileTimestamp(~)」で取得した最新のタイムスタンプを引いて、dhhmmss(~)で表示整形しています。


    すみません。
    先ほどのコメントに一部間違いがありました。
    正しくは以下です。($dhhmmssの$が余分です・・・)

    echo "最終更新時刻は ". dhhmmss($ntime) ."前です。";

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません