PseudoPsyche
PseudoPsyche

Reputation: 4592

How to monitor individual files with Ruby listen gem?

I'm trying to use the listen gem (https://github.com/guard/listen) to listen to specific files, but so far have only been able to get the base functionality of listening to whole directories working properly.

Here's an example of what I'm trying at the moment:

require "listen"

module FileTracker
  filedir = "/home/user/dir"
  filenames = [ "file1", "file2" ]

  # Should only track 'file1' and 'file2' in this directory
  listener = Listen.to(filedir, only: filenames) do |modified, added, removed|
    puts "Updated: " + modified.first
  end

  listener.start
  sleep
end

I have also tried simply specifying a single filename as a string for the only: parameter, but that didn't work either.

My end goal is to be able to track a list of user-defined files in various directories for changes. I only want to track each specific file, not the the entire directory.

Upvotes: 4

Views: 2039

Answers (2)

Cezary Baginski
Cezary Baginski

Reputation: 2095

just a few tips you might find useful:

  1. To quote the regexp properly and use regexp groups without capturing them:

    filenames = %w(foo.txt bar.js)
    listen_regex = /(?:#{file.map { |f| Regexp.quote(f) } * '|'})$
    

(Should be a little more reliable).

  1. More importantly, there are a few notes about Listen:

    • what listen physically watches depends on the backend, e.g. polling modes just scans the given directories recursively (excluding files matching the ignore regexen), while e.g. rb-fsevent on MacOSX watches directories and physically scans those directories for changes every time.

So there's really no such thing as "listening to files", because Listen operates on directories and filters out files (and sometimes directories) based on ignore rules.

This is important if you have frequently modified files, e.g. log files or database files in your project directory, because every time they are changed, the changes are triggered anyway (except when polling) - you just won't see that because of ignores.

  1. To see what's going on in Listen, there's a cool debug option: LISTEN_GEM_DEBUGGING (see README). Depending on the value (1 or 2) you see what system events Listen is getting under the hood, what it's ignoring and how long stuff takes (see Listen wiki for more info).

Let me know if you have any feedback on the docs or on Listen itself.

Have a nice day!

Upvotes: 1

PseudoPsyche
PseudoPsyche

Reputation: 4592

I wasn't paying attention to what I was doing here. only: clearly takes a regex, which I was obviously failing to construct and provide. Hopefully this can help someone else out who may need to use listen to watch or ignore specific files.

Here is an example of my working solution:

module FileTracker
  filedir = "/home/user/dir"
  filenames = [ "file1", "file2" ]

  listenRegex = filenames.join("$|").gsub!(".", "\.") + "$"

  # Should only track 'file1' and 'file2' in this directory
  listener = Listen.to(filedir, only: /#{listenRegex}/) do |modified, added, removed|
    puts "Updated: " + modified.first
  end

  listener.start
  sleep
end

Upvotes: 4

Related Questions