読者です 読者をやめる 読者になる 読者になる

ファイルを監視するやつ

http://subtech.g.hatena.ne.jp/secondlife/20070228/1172625779

もう素晴らしい回答が出てきてるような気もしますがとりあえず勉強がてらやってみました。Observable初めて使った。

# lib/file/stat/observable.rb
require 'observer'
require 'thread'

$LOAD_PATH.unshift(File.expand_path(File.join(File.dirname(__FILE__), '../../')))
require 'file/stat/observe_manager'

class File
  class Stat
    class Observer
      def initialize(file,  &block)
        unless File.exists? file
          raise ArgumentError
        end

        @file = file
        @proc = block 
      end

      attr_reader :file

      def update file, result
        if @file == file
          @proc.call(@file, result)
        end
      end
    end
  end
end

# lib/file/stat/observe_manager.rb
require File.join(File.dirname(__FILE__), '../../', 'file/stat/observer')

class File
  class Stat
    class ObserveManager
      include Observable

      def initialize grob_expr=nil, &block
        @interval = 1 

        if grob_expr
          add_files grob_expr, &block
        end 
      end 

      attr_accessor :interval
      def add_files grob_expr, &block
        Dir[grob_expr].each do |file|
          add_observer(File::Stat::Observer.new(file, &block))
        end 
      end 

      def observe(method)
        return unless method.to_s =~ /.*time.*/ # TODO: とりあえずtime系のみサポート

        threads = []
        @observer_peers.each do |observer| # @observer_peers come from Observable
            threads << Thread.new do
              last = Time.now
              loop do
                begin
                  sleep(@interval)
                  current = File.__send__(method, observer.file)
                  if current > last
                    changed
                    notify_observers(observer.file, current)
                    last = current
                  end   
                rescue Exception
                  next
                end   
              end   
            end
           end     
        threads.each {|t| t.join }
      rescue Interrupt
        return
      end
    end
  end
end

if $PROGRAM_NAME == __FILE__
  observe_manager = File::Stat::ObserveManager.new('*.txt') {|file, result| puts "#{file} updated on #{result}" }
  observe_manager.observe(:mtime)
end

例外処理あたりが手抜き気味です。

追記

id:secondlifeさんよりライセンスについて質問がありました。ライセンスはRubyと同様でお願いします。作者名はKeiji Yoshimiが無難です。

さらに色々変更してます。
http://d.hatena.ne.jp/walf443/20070302/1172849934
http://d.hatena.ne.jp/walf443/20070302/1172854994