The project is in a healthy, maintained state
Watch files and directories for changes using polling. Detects created, modified, and deleted files with configurable intervals and glob patterns.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies
 Project Readme

philiprehberger-file_watcher

Tests Gem Version Last updated

File system change detection with polling and callbacks

Requirements

  • Ruby >= 3.1

Installation

Add to your Gemfile:

gem "philiprehberger-file_watcher"

Or install directly:

gem install philiprehberger-file_watcher

Usage

require "philiprehberger/file_watcher"

# Block-based watching (blocking, Ctrl+C to stop)
Philiprehberger::FileWatcher.watch("./src", interval: 0.5, glob: "**/*.rb") do |change|
  puts "#{change.type}: #{change.path}"
end

Watcher Instance

require "philiprehberger/file_watcher"

watcher = Philiprehberger::FileWatcher::Watcher.new(
  ["./src", "./lib"],
  interval: 1.0,
  glob: "**/*"
)

watcher.on(:created)  { |change| puts "Created: #{change.path}" }
watcher.on(:modified) { |change| puts "Modified: #{change.path}" }
watcher.on(:deleted)  { |change| puts "Deleted: #{change.path}" }

watcher.start
# ... do other work ...
watcher.stop

Exclusion Patterns

require "philiprehberger/file_watcher"

watcher = Philiprehberger::FileWatcher::Watcher.new(
  "./src",
  glob: "**/*",
  exclude: ["**/*.log", "**/tmp/**"]
)
watcher.on(:any) { |change| puts change }
watcher.start

Change Debouncing

require "philiprehberger/file_watcher"

# Only fire after 0.5 seconds of inactivity per file
watcher = Philiprehberger::FileWatcher::Watcher.new("./src", debounce: 0.5)
watcher.on(:modified) { |change| puts "Settled: #{change.path}" }
watcher.start

Batch Change Reporting

require "philiprehberger/file_watcher"

watcher = Philiprehberger::FileWatcher::Watcher.new("./src", interval: 1.0)
watcher.on(:batch) { |changes| puts "#{changes.size} files changed" }
watcher.start

Error Handling

require "philiprehberger/file_watcher"

watcher = Philiprehberger::FileWatcher::Watcher.new("./src")
watcher.on(:error) { |exception, path| warn "Error on #{path}: #{exception.message}" }
watcher.on(:any) { |change| puts change }
watcher.start

Snapshot

require "philiprehberger/file_watcher"

watcher = Philiprehberger::FileWatcher::Watcher.new("./src")
watcher.start

snapshot = watcher.snapshot
snapshot.each do |path, info|
  puts "#{path}: mtime=#{info[:mtime]}, size=#{info[:size]}"
end

API

FileWatcher.watch(paths, interval:, glob:, exclude:, debounce:, &block)

Parameter Type Default Description
paths String, Array<String> required Directories or files to watch
interval Float 1.0 Polling interval in seconds
glob String "**/*" Glob pattern for matching files
exclude Array<String> [] Glob patterns to exclude from watching
debounce Float, nil nil Debounce interval in seconds
&block Block required Called with each Change object

Blocking method. Stops on Interrupt (Ctrl+C).

FileWatcher::Watcher

Method Description
.new(paths, interval: 1.0, glob: "**/*", exclude: [], debounce: nil) Create a new watcher instance
#on(type, &block) Register a callback for :created, :modified, :deleted, :any, :error, or :batch
#start Start watching in a background thread
#stop Stop watching and join the thread
#running? Returns true if the watcher is active
#snapshot Returns a hash of {path => {mtime:, size:}} for all tracked files

FileWatcher::Change

Method Description
#path Absolute path to the changed file
#type Change type: :created, :modified, or :deleted
#to_s Human-readable string, e.g. "created: /path/to/file.rb"

Development

bundle install
bundle exec rspec
bundle exec rubocop

Support

If you find this project useful:

Star the repo

🐛 Report issues

💡 Suggest features

❤️ Sponsor development

🌐 All Open Source Projects

💻 GitHub Profile

🔗 LinkedIn Profile

License

MIT