ファイルを監視するやつ
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