40.20 Notifications on File Changes
Several operating systems support watching of filesystems for changes of files. If configured properly, Emacs links a respective library like inotify
, kqueue
, gfilenotify
, or w32notify
statically. These libraries enable watching of filesystems on the local machine.
It is also possible to watch filesystems on remote machines, see Remote Files in The GNU Emacs Manual This does not depend on one of the libraries linked to Emacs.
Since all these libraries emit different events on notified file changes, there is the Emacs library filenotify
which provides a unified interface. Lisp programs that want to receive file notifications should always use this library in preference to the native ones.
function
file-notify-add-watch file flags callbackβ
Add a watch for filesystem events pertaining to file
. This arranges for filesystem events pertaining to file
to be reported to Emacs.
The returned value is a descriptor for the added watch. Its type depends on the underlying library, it cannot be assumed to be an integer as in the example below. It should be used for comparison by equal
only.
If the file
cannot be watched for some reason, this function signals a file-notify-error
error.
Sometimes, mounted filesystems cannot be watched for file changes. This is not detected by this function, a non-nil
return value does not guarantee that changes on file
will be notified.
flags
is a list of conditions to set what will be watched for. It can include the following symbols:
change
β
watch for file changes
attribute-change
β
watch for file attribute changes, like permissions or modification time
If file
is a directory, changes for all files in that directory will be notified. This does not work recursively.
When any event happens, Emacs will call the callback
function passing it a single argument event
, which is of the form
(descriptor action file [file1])
descriptor
is the same object as the one returned by this function. action
is the description of the event. It could be any one of the following symbols:
created
β
file
was created
deleted
β
file
was deleted
changed
β
file
βs contents has changed; with w32notify
library, reports attribute changes as well
renamed
β
file
has been renamed to file1
attribute-changed
β
a file
attribute was changed
stopped
β
watching file
has been stopped
Note that the w32notify
library does not report attribute-changed
events. When some fileβs attribute, like permissions or modification time, has changed, this library reports a changed
event. Likewise, the kqueue
library does not report reliably file attribute changes when watching a directory.
The stopped
event reports, that watching the file has been stopped. This could be because file-notify-rm-watch
was called (see below), or because the file being watched was deleted, or due to another error reported from the underlying library.
file
and file1
are the name of the file(s) whose event is being reported. For example:
(require 'filenotify)
β filenotify
(defun my-notify-callback (event)
(message "Event %S" event))
β my-notify-callback
(file-notify-add-watch
"/tmp" '(change attribute-change) 'my-notify-callback)
β 35025468
(write-region "foo" nil "/tmp/foo")
β Event (35025468 created "/tmp/.#foo")
Event (35025468 created "/tmp/foo")
Event (35025468 changed "/tmp/foo")
Event (35025468 deleted "/tmp/.#foo")
(write-region "bla" nil "/tmp/foo")
β Event (35025468 created "/tmp/.#foo")
Event (35025468 changed "/tmp/foo")
Event (35025468 deleted "/tmp/.#foo")
(set-file-modes "/tmp/foo" (default-file-modes))
β Event (35025468 attribute-changed "/tmp/foo")
Whether the action renamed
is returned, depends on the used watch library. Otherwise, the actions deleted
and created
could be returned in a random order.
(rename-file "/tmp/foo" "/tmp/bla")
β Event (35025468 renamed "/tmp/foo" "/tmp/bla")
(delete-file "/tmp/bla")
β Event (35025468 deleted "/tmp/bla")
function
file-notify-rm-watch descriptorβ
Removes an existing file watch specified by its descriptor
. descriptor
should be an object returned by file-notify-add-watch
.
function
file-notify-valid-p descriptorβ
Checks a watch specified by its descriptor
for validity. descriptor
should be an object returned by file-notify-add-watch
.
A watch can become invalid if the file or directory it watches is deleted, or if the watcher thread exits abnormally for any other reason. Removing the watch by calling file-notify-rm-watch
also makes it invalid.
(make-directory "/tmp/foo")
β Event (35025468 created "/tmp/foo")
(setq desc
(file-notify-add-watch
"/tmp/foo" '(change) 'my-notify-callback))
β 11359632
(file-notify-valid-p desc)
β t
(write-region "bla" nil "/tmp/foo/bla")
β Event (11359632 created "/tmp/foo/.#bla")
Event (11359632 created "/tmp/foo/bla")
Event (11359632 changed "/tmp/foo/bla")
Event (11359632 deleted "/tmp/foo/.#bla")
;; Deleting a file in the directory doesn't invalidate the watch.
(delete-file "/tmp/foo/bla")
β Event (11359632 deleted "/tmp/foo/bla")
(write-region "bla" nil "/tmp/foo/bla")
β Event (11359632 created "/tmp/foo/.#bla")
Event (11359632 created "/tmp/foo/bla")
Event (11359632 changed "/tmp/foo/bla")
Event (11359632 deleted "/tmp/foo/.#bla")
;; Deleting the directory invalidates the watch.
;; Events arrive for different watch descriptors.
(delete-directory "/tmp/foo" 'recursive)
β Event (35025468 deleted "/tmp/foo")
Event (11359632 deleted "/tmp/foo/bla")
Event (11359632 deleted "/tmp/foo")
Event (11359632 stopped "/tmp/foo")
(file-notify-valid-p desc)
β nil