1

ディレクトリのリストがあるとしましょう。各ディレクトリには、考慮したいサブディレクトリが含まれている場合と含まれていない場合があります。

また、リスト内のディレクトリごとに 1 つのタイムスタンプのリストがあるとします (ただし、サブディレクトリではありません)。これらは、暗黙的なタイムゾーンを持つ日付と時刻として知られているため、比較が容易になる場合は、かなり簡単に Unix タイムスタンプに変換できます。

リストされた各ディレクトリについて、問題のディレクトリのタイムスタンプよりも新しい (atime ではなく mtime または ctime に関して) ディレクトリ内にファイルが存在するかどうかを調べるにはどうすればよいですか?

どの特定のファイルがタイムスタンプよりも新しいかについてはあまり関心がありません。そのようなファイルが存在するかどうかだけです。

基本的に、特定の時点以降に一連のディレクトリのいずれか内のファイルが変更された場合に実行時に特定のアクションを実行するスクリプトを作成し、何かが変更されたかどうかを検出する方法を考え出す必要があります。かわった。

4

1 に答える 1

7

あなたの問題は、複数の簡単な下位問題に変換できます

  1. Q: ディレクトリ内の各ファイルを再帰的に調べるにはどうすればよいですか?

    A: use File::Find. これは少し似ています

    use File::Find;
    
    find sub {
      return unless -f;
      if (file_is_newer_than($timestamp)) {
        do something;
      },
    }, $top_dir;
    
  2. Q: 複数のディレクトリに対してこれを行うにはどうすればよいですか?

    A: foreach ループでラップします。

    for my $dir_time (["./foo", 1234567890], ["./bar", 1230987654]) {
      my ($top_dir, $timestamp) = @$dir_time;
      # above code
    }
    
  3. Q: ファイルが新しいかどうかを確認するにはどうすればよいですか?

    A:またはのstat場合は、結果をタイムスタンプと比較します。例えばmtimectime

    use File::stat;
    
    say "$_ is new!" if stat($_)->mtime > $timestamp;
    
  4. Q: そのようなファイルが存在するかどうかだけに興味があります。どうすれば短くすることができfindますか?

    A:トリッキーです。returnからだけではできませんfind。これは、渡した coderef から終了するためです。代わりに、exceptions-for-control-flow アンチパターンを使用できます。

    eval {
      find {
        wanted => sub {
          return unless -f;
          die "New file found\n" if stat($_)->mtime > $timestamp;
        },
        no_chdir => 1,
      } $top_dir;
    };
    if ($@) {
      # I should really use exception objects here…
      if ($@ eq "New file found\n") {
        say "New file in $top_dir found";
      } else {
        die $@;  # rethrow error
      }
    }
    

    no_chdir例外ハンドラで正しい作業ディレクトリを復元する必要がないように、オプションを設定しました。

    または、ラベル付きブロックでループ制御を使用できます。

    DIR: for my $dir_time (...) {
      my ($top_dir, $timestamp) = @$dir_time;
      RECURSION: {   
        find {
          wanted => sub {
            return unless -f;
            last RECURSION if stat($_)->mtime > $timestamp; # exit the RECURSION block
          },
          no_chdir => 1,
        } $top_dir;
        # if we are here, no newer file was found.
        next DIR; # make sure to skip over below code; go to next iteration
      }
      # this code only reached when a newer file was found
      say "New file found";
    }
    

    これは制御フローの例外を悪用しませんが、警告をトリガーします。

    Exiting subroutine via last
    

    でこれを黙らせることができno warnings 'exiting'ます。

注意: ここにあるすべてのコードはまったくテストされていません。

于 2013-07-28T19:09:52.333 に答える