On GNU/Linux exists a library called inotify which does that, notifies for changes(change, create, delete) of files into a directory. Over Mac there is FSEvents, which essentially do the same as inotify, with some exceptions of course.
Now, what happened if I have 2 servers which I want to monitor for file changes?. You could say: «write one app and run on 2 servers». Yeah!, nice answer, but 1 of them is running GNU/Linux and the other one is running MacOS, so we need something like Ruby to do so.
First we install fssm(File System State Monitor) from rubygems:
gem install fssm
Maybe you need do the above as root. Next go to your favorite editor, I use Geany.
Of course, the first lines will be:
#!/usr/bin/env ruby require 'rubygems' require 'fssm'
The first line calls for the ruby interpreter and the next 2 loads rubygems and fssm ruby extensions.
Now go to the magic code, it’s pretty simple and easy to undestand.
FSSM.monitor("/tmp/test") do
update do |b, r|
puts "Someone changes the file '#{r}' into '#{b}'"
end
create do |b, r|
puts "Someone creates the file '#{r}' into '#{b}'"
end
delete do |b, r|
puts "Someone deletes the file '#{r}' into '#{b}'"
end
end
The first line enters to a loop that watch for filesystem changes only into /tmp/test directory.
The second line states which actions gonna take the program if the some file inside the /tmp/test directory has been updated and passes the variables b and r to the block(in this case just line number 3). r is the relative path to the updated, b is the absolute path(/tmp/test in this case); then a message is printed on the screen.
The code for the created and deleted files are the same.
Now, the FSSM.monitor has 3 possible arguments, we just use 1 of them in the above example.
The second parameter is a glob pattern(or array of glob patterns) that the files must match to be watched by fssm, if this parameter is not specified, the default is **/*.
The third parameter is for watching directories. By default, fssm watch just for file changes, if we want to watch directories too we need to pass the option here, doing this :directories => true, and additionally, the blocks for update, delete and create must have another block variable:
delete do |b, r, t|
puts "Someone delete #{r} into #{b} which is a #{t == :directory ? 'directory' : 'file'}"
end
Where t is the type, it means if is a directory or a file, we check for this in a «short» if statement. t variable can be the symbols :directory or :file. AFAIK this will not work as expected on MacOS, I appreciate if someone can confirm, I’m a poor guy and I don’t own a Mac.
. Anyway it don’t watch for created, deleted or updated directories, but if you create a directory inside /tmp/test and then create a file inside, it will be detected.
So, the complete code with checking for directories is:
#!/usr/bin/env ruby
require 'rubygems'
require 'fssm'
FSSM.monitor("/tmp/test", '**/*', :directories => true) do
update do |b, r, t|
puts "Someone changes #{r} into #{b} which is a #{t == :directory ? 'directory' : 'file'}"
end
create do |b, r, t|
puts "Someone create #{r} into #{b} which is a #{t == :directory ? 'directory' : 'file'}"
end
delete do |b, r, t|
puts "Someone delete #{r} into #{b} which is a #{t == :directory ? 'directory' : 'file'}"
end
end
That’s it!. Now we can watch for filesystem changes in many different systems. It’s so nice and useful. Of course we need to develop and work a little more to do something nicer.
I hope this will help someone, works for me.
See you soon.


