Next: , Previous: , Up: fswatch   [Contents][Index]


3 Tutorial Introduction to fswatch

This chapter is a tutorial walk-through on the most common use cases where fswatch is useful:

3.1 Detecting File System Changes

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.

3.2 Observing File System Changes

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:

3.2.1 Event details

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.

3.2.2 Parseability Issues

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 ‘NUL3 character, it suffers from two classes of parseability issues:

  • The default choice of using ‘\n’ as record separator may lead to unexpected results because a file name can legally contain ‘\n’. For this reason, along the line of what other tools such as find and xargs already do, the ‘NUL’ character (‘\0’) can alternatively be used:
    /absolute-path( flag)*\0
    
  • Since a file name may contain spaces, this record structure is not unambigually parseable if more than one event flag is present: in this case, any subset [0, x], x < n - 1 of the n event flags may be part or the file name and hence any parse result would be indeterminate.

Both issues can be solved using a custom record format (see Custom Record Formats).

3.2.3 Numeric Event Flags

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.

3.3 Processing fswatch Output

Very 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:

3.4 Detecting the Boundaries of a Batch of Changes

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.

3.5 Receiving a Single Event

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
...
$

Footnotes

(1)

In the context of this manual (unless specified otherwise), file system object refers undistinctively to files, directories and symbolic links.

(2)

A batch is an iteration of fswatch scanning logic, whose frequency is \nu = l^{-1}, where l is the latency.

(3)

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: fswatch   [Contents][Index]