Monitoring directory changes with fswatch on OS X/macOS

Have a dream? Start learning your way toward it with courses from $12.99. Shop now for extra savings1px

If you want to monitor file changes in a directory on an Apple OS X/macOS system, one way to do so is using fswatch, a cross-platform file change monitor. The utility will allow you to monitor which files in the directory have been changed, though it doesn't report on the particular changes made to the content of the files. You can track the addition and deletion of files or whether files in the monitored directory are modified. On a Mac OS X system, you can install the software using the Homebrew package management system - see Installing Homebrew on Mac OS X for instructions on installing the software. Once Homebrew is installed, you can install fswatch using the command brew install fswatch in a Terminal window, which provides a command-line interface (CLI). The program will be installed in /usr/local/bin. Once it is installed, you can view help information by typing fswatch -h at a Terminal window shell prompt.

Udemy Generic Category (English)120x600
$ fswatch -h
fswatch 1.14.0

Usage:
fswatch [OPTION] ... path ...

Options:
 -0, --print0          Use the ASCII NUL character (0) as line separator.
 -1, --one-event       Exit fswatch after the first set of events is received.
     --allow-overflow  Allow a monitor to overflow and report it as a change event.
     --batch-marker    Print a marker at the end of every batch.
 -a, --access          Watch file accesses.
 -d, --directories     Watch directories only.
 -e, --exclude=REGEX   Exclude paths matching REGEX.
 -E, --extended        Use extended regular expressions.
     --filter-from=FILE
                       Load filters from file.
     --format=FORMAT   Use the specified record format.
 -f, --format-time     Print the event time using the specified format.
     --fire-idle-event Fire idle events.
 -h, --help            Show this message.
 -i, --include=REGEX   Include paths matching REGEX.
 -I, --insensitive     Use case insensitive regular expressions.
 -l, --latency=DOUBLE  Set the latency.
 -L, --follow-links    Follow symbolic links.
 -M, --list-monitors   List the available monitors.
 -m, --monitor=NAME    Use the specified monitor.
     --monitor-property name=value
                       Define the specified property.
 -n, --numeric         Print a numeric event mask.
 -o, --one-per-batch   Print a single message with the number of change events.
 -r, --recursive       Recurse subdirectories.
 -t, --timestamp       Print the event timestamp.
 -u, --utc-time        Print the event time as UTC time.
 -x, --event-flags     Print the event flags.
     --event=TYPE      Filter the event by the specified type.
     --event-flag-separator=STRING
                       Print event flags using the specified separator.
 -v, --verbose         Print verbose output.
     --version         Print the version of fswatch and exit.

Available monitors in this platform:

  fsevents_monitor
  kqueue_monitor
  poll_monitor

See the man page for more information.

Report bugs to <enrico.m.crisostomo@gmail.com>.
fswatch home page: <https://github.com/emcrisostomo/fswatch>.
$

A man page is also installed, so you can type man fswatch to view instructions on using the application. A link to the man page can be found in /usr/local/share/man/man7.

$ ls /usr/local/share/man/man7
fswatch.7	soxeffect.7	soxformat.7

If I want to monitor changes to a particular directory, e.g., ~/Documents/Temp, I could use the command below (you can terminate the program to stop monitoring with Ctrl-C):

$ fswatch ~/Documents/Temp
/Users/jasmith1/Documents/Temp/smime.p7m
/Users/jasmith1/Documents/Temp/.DS_Store
^C$

When I deleted the smime.p7m file from the directory, I saw the two lines of output above displayed. If I want more detail on what occured to the file, I can use the -x or --event-flags option. E.g., if I move the file cert8.db to the trash from a Finder window, I see the following output:

$ fswatch --event-flags ~/Documents/Temp
/Users/jmcamer1/Documents/Temp/cert8.db Renamed IsFile
/Users/jmcamer1/Documents/Temp/.DS_Store PlatformSpecific Updated IsFile
^C$

From the output, it appears I renamed the file, but I actually removed it from the directory by sending it to the trash from the Finder window. However, if I use a rm (remove) command in another Terminal tab to remove the file 10-12 LRC.pdf I see "Removed" as the event. And when I modify the Jessica.txt file, I see "Updated" among the event flags listed. When I created a file, test.txt with the touch command in that other Terminal tab, I see "Created" listed as the event flag.

Advanced Mac OS X - Technical and Security Skills
Advanced Mac OS X
Technical and Security Skills
1x1 px

$ fswatch --event-flags ~/Documents/Temp
/Users/jasmith1/Documents/Temp/10-12 LRC.pdf Removed IsFile
/Users/jasmith1/Documents/Temp/Jessica.txt.sb-6c9fd7dc-1J3Whm Created PlatformSp
ecific Renamed Updated OwnerModified AttributeModified IsFile
/Users/jasmith1/Documents/Temp/Jessica.txt PlatformSpecific Renamed IsFile
/Users/jasmith1/Documents/Temp/Jessica.txt.sb-6c9fd7dc-cHWhwR Removed Renamed Up
dated OwnerModified IsFile
/Users/jasmith1/Documents/Temp/test.txt Created IsFile
^C$

If I use the command rm -rf ~/Documents/Temp/tmp to remove a subdirectory tmp and all the files and directories within it, I see the following output:

$ fswatch --event-flags ~/Documents/Temp
/Users/jmcamer1/Documents/Temp/tmp/[Content_Types].xml Removed IsFile
/Users/jmcamer1/Documents/Temp/tmp/_rels/.rels Removed IsFile
/Users/jmcamer1/Documents/Temp/tmp/_rels Removed IsDir
/Users/jmcamer1/Documents/Temp/tmp/docProps/app.xml Removed IsFile
/Users/jmcamer1/Documents/Temp/tmp/docProps/core.xml Removed IsFile
/Users/jmcamer1/Documents/Temp/tmp/docProps/thumbnail.jpeg Removed IsFile
/Users/jmcamer1/Documents/Temp/tmp/docProps Removed IsDir
/Users/jmcamer1/Documents/Temp/tmp/lu251609cvgcn.tmp Removed IsFile
/Users/jmcamer1/Documents/Temp/tmp/lu251609cvgcn.xlsx Removed IsFile
/Users/jmcamer1/Documents/Temp/tmp/xl/_rels/workbook.xml.rels Removed IsFile
/Users/jmcamer1/Documents/Temp/tmp/xl/_rels Removed IsDir
/Users/jmcamer1/Documents/Temp/tmp/xl/sharedStrings.xml Removed IsFile
/Users/jmcamer1/Documents/Temp/tmp/xl/styles.xml Removed IsFile
/Users/jmcamer1/Documents/Temp/tmp/xl/theme/theme1.xml Removed IsFile
/Users/jmcamer1/Documents/Temp/tmp/xl/theme Removed IsDir
/Users/jmcamer1/Documents/Temp/tmp/xl/workbook.xml Removed IsFile
/Users/jmcamer1/Documents/Temp/tmp/xl/worksheets/sheet1.xml Removed IsFile
/Users/jmcamer1/Documents/Temp/tmp/xl/worksheets Removed IsDir
/Users/jmcamer1/Documents/Temp/tmp/xl Removed IsDir
/Users/jmcamer1/Documents/Temp/tmp Removed IsDir
^C$

You can see that "IsFile" is shown for events affecting particular files while "IsDir" is shown when the subdirectories are removed.