Next: Invoking fswatch
, Previous: Introduction, Up: Top [Contents][Index]
fswatch
This chapter is a tutorial walk-through on the most common use cases
where fswatch
is useful:
fswatch
output.
A common use case is detecting file system changes in a set of
file system objects1 where
the details of a change are irrelevant. This mode of operation
is called bulk mode and fswatch
will only dump a
single event record per batch2 containing the number
of affected file system objects. No other details are avaible in the
event record.
The most common application of this mode of operation is performing a
bulk action on all the observed file system objects, such as a
synchronization with rsync
, which will serve us as an
example. In this case, a change event triggers the execution of a
synchronization script, no matter the event type kind nor the object
the event affects.
To run fswatch
in batch mode, the (-o,
--one-per-batch) must be used:
$ fswatch -o path ... 2 10
The (-l, --latency) option can be used to set the latency according to the requirements:
$ fswatch -o -l 5 path ... 4 7
This way, you can respond to change events in a way which is (or can easily be) path-independent (because you are not receiving any event detail) and you prefer to ‘bubble’ events together to reduce the overhead of the command being executed.
In bulk mode the output of fswatch
is guaranteed to have the
following structure:
number\n
where ‘number’ is an integer value and ‘\n’ is the new line
character. A line with this structure is very easy to read with
either xargs
or the read
builtin:
$ fswatch -o path | while read num ; \ do \ ... \ done
In many scripts of this kind, the num variable can even be ignored.
Besides the batch mode, fswatch
provides a main mode
providing the full change events details and the file system objects
they refer to. The main mode is fswatch
’s default
mode of operation and needs no specific flags to be activated.
In this mode, fswatch
outputs change events to the standard
output. By default, only the affected file name is printed and the
change event record structure has the following structure:
path\n
where path is the full path of the changed file system object.
fswatch
lets users customize the format of the event record
and the information it includes. For example:
printf
-like format
string.
Beside the full path of the change object, details on the kind of change event can be obtained using the (-x, --event-flags) option:
$ fswatch -xr /path/to/observe /path/to/observe Created Renamed OwnerModified IsFile ...
In this case, a space-separated list of change flags are printed after the path of the changed object. The record structure is thus:
/absolute-path flag ( flag)*
where ‘flag’ is an event flag. At least one event flag is always present, and additional ones are ‘bubbled’ into the same record and separated by space. For more information on event flags see Event Flags.
The default record format is intuitive and human-readable. However, since a Unix file name may contain any character but the path separator ‘/’ and the ‘NUL’3 character, it suffers from two classes of parseability issues:
find
and xargs
already do, the ‘NUL’
character (‘\0’) can alternatively be used:
/absolute-path( flag)*\0
Both issues can be solved using a custom record format (see Custom Record Formats).
Instead of using user-friendly event flag names, as seen in the previous section, numeric event flags can be used instead. Currently, the real advantage this method offers, despite possibly cleaner flag-decoding logic, is the availability of a non-ambigous event record representation.
To instruct fswatch
to print numeric event flags, the
(-n, --numeric) option must be used:
$ fswatch -xnr /path/to/observe /absolute-path 2058
The numeric event flag value is the bitwise OR of the individual event flag values, that are powers of 2. In the previous example, the flag 2058 is decomposed in powers of 2 as 2058 = 2048 + 8 + 2 = 2^{11} + 2^3 + 2, that is, the first, the third and the eleventh event flags.
fswatch
OutputVery often you wish to not only receive an event, but also react to
it. The simplest way to do it is piping the output of
fswatch
to another process. Since in Unix and Unix-like
file system file names may potentially contain any character but
‘NUL’ (‘\0’) and the path separator (‘/’),
fswatch
has a specific mode of operation when its output
must be piped to another process. When the (-0,
--print0) option is used, fswatch
will use the
‘NUL’ character as record separator, thus allowing any other
character to appear in a path.
This is important because many commands and shell builtins (such as
read
) split lines using the newline character (‘\n’)
and words using the characters in $IFS
, which by default
contains characters which may be present in a file name, resulting in
a wrong event path being received and processed.
The simplest way to pipe fswatch
’s output to another program
is using xargs
:
$ fswatch -0 (opts)* (paths)+ | xargs -0 -n 1 -I {} command
The command in this example does the following:
fswatch -0
will split records using the ‘NUL’
character.
xargs -0
will split records using the ‘NUL’ character.
This is required to correctly match impedance with fswatch
.
xargs -n 1
will invoke command
every record. If
you want to do it every x
records, then use xargs
-n x
.
xargs -I {}
will substitute occurrences of {}
in
command
with the parsed argument. If the command you are
running does not need the event path name, just delete this option.
If you prefer using another replacement string, substitute {}
with another string of your choice.
If a process or script is piped to fswatch
output, sometimes
it would be desirable to detect the ‘boundaries’ of a batch of
changes. This way, the process receiving the stream of changes would
rely on the timings imposed by the latency settings of
fswatch
to start a phase of events processing after a
phase or events gathering. The --batch-marker option
can be used to accomplish this task:
$ fswatch --batch-marker -r ~ /home/fswatch/.zsh_history.LOCK NoOp /home/fswatch/.zsh_history.new /home/fswatch/.zsh_history /home/fswatch/.zsh_history.LOCK NoOp
In this example, the ‘NoOp’ records mark the end of the 1 second
batches of events output by fswatch
. The batch marker can
be customized. For more information Batch Marker.
Another feature of fswatch
is the possibility of receiving a
single event and exit. This is most useful when existing
scripts processing events include the restart logic of
fswatch
. This use case is implemented by the -1,
--one-event option:
$ fswatch -1 /path/to/watch /path/to/watch/child0 /path/to/watch/child1 ... $
In the context of this manual (unless specified otherwise), file system object refers undistinctively to files, directories and symbolic links.
A batch is an iteration
of fswatch
scanning logic, whose frequency is \nu =
l^{-1}, where l is the latency.
Depending on the file system being used, other restrictions may apply. However, for file system portability reasons, you should consider ‘NUL’ as the only forbidden character.
Next: Invoking fswatch
, Previous: Introduction, Up: Top [Contents][Index]