An Elixir file change watcher wrapper based on FS, the native file system listener.
- MacOS - fsevent
- GNU/Linux, FreeBSD, DragonFly and OpenBSD - inotify
- Windows - inotify-win
On MacOS 10.14, to compile mac_listener
, run:
open /Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg
On newer versions this file doesn't exist. But it still should work just fine as long as you have xcode installed.
Add file_system
to the deps
of your mix.exs
defmodule MyApp.Mixfile do
use Mix.Project
def project do
...
end
defp deps do
[
{:file_system, "~> 1.0", only: :test},
]
end
...
end
You can spawn a worker and subscribe to events from it:
{:ok, pid} = FileSystem.start_link(dirs: ["/path/to/some/files"])
FileSystem.subscribe(pid)
or
{:ok, pid} = FileSystem.start_link(dirs: ["/path/to/some/files"], name: :my_monitor_name)
FileSystem.subscribe(:my_monitor_name)
The pid
you subscribed from will now receive messages like:
{:file_event, worker_pid, {file_path, events}}
and
{:file_event, worker_pid, :stop}
defmodule Watcher do
use GenServer
def start_link(args) do
GenServer.start_link(__MODULE__, args)
end
def init(args) do
{:ok, watcher_pid} = FileSystem.start_link(args)
FileSystem.subscribe(watcher_pid)
{:ok, %{watcher_pid: watcher_pid}}
end
def handle_info({:file_event, watcher_pid, {path, events}}, %{watcher_pid: watcher_pid} = state) do
# Your own logic for path and events
{:noreply, state}
end
def handle_info({:file_event, watcher_pid, :stop}, %{watcher_pid: watcher_pid} = state) do
# Your own logic when monitor stop
{:noreply, state}
end
end
For each platform, you can pass extra options to the underlying listener process.
Each backend supports different extra options, check backend module documentation for more details.
Here is an example to get instant notifications on file changes for MacOS:
FileSystem.start_link(dirs: ["/path/to/some/files"], latency: 0, watch_root: true)