Monitoring File System Changes on macOS: A Comprehensive Guide to fswatch and Alternatives

Dec 05, 2025 · Programming · 13 views · 7.8

Keywords: macOS | file monitoring | fswatch | launchd | FSEvents

Abstract: This article provides an in-depth exploration of solutions for monitoring folder changes and automatically executing scripts on macOS. It focuses on the fswatch tool based on the FSEvents API, covering installation methods, basic syntax, advanced options, and practical examples. Additionally, it briefly compares launchd as a system-level monitoring alternative, helping developers choose the appropriate tool based on their needs.

Introduction

In macOS development environments, there is often a need to monitor specific folders for changes and automatically execute corresponding actions when files are created, modified, or deleted. While Linux systems have mature tools like inotifywait, macOS requires different technical approaches. This article details two mainstream methods: the fswatch tool based on the FSEvents API and the system service launchd.

fswatch: The Core Tool for macOS File System Monitoring

fswatch is a cross-platform file system monitoring tool that leverages the FSEvents API on macOS for efficient monitoring. FSEvents is a macOS-specific file system event notification framework that offers lower overhead and higher real-time performance compared to polling methods.

Installation Methods

It is recommended to use Homebrew for installation:

brew update
brew install fswatch

For manual compilation and installation, execute the following commands:

cd /tmp
git clone https://github.com/alandipert/fswatch
cd fswatch/
make
cp fswatch /usr/local/bin/fswatch

Manual installation requires Xcode command line tools to provide C compiler support.

Basic Usage Patterns

For fswatch version 1.x and above, the recommended pattern uses pipes combined with xargs:

fswatch -o ~/watch_path | xargs -n1 -I{} ~/script_path/change.sh

The -o option causes fswatch to output the number of events rather than detailed event information, which is then passed to the processing script via xargs. -I{} specifies the replacement string to prevent the event count from being appended to the end of the command.

The syntax for earlier version 0.x is simpler:

fswatch ~/watch_path ~/script_path/change.sh

Advanced Configuration Options

fswatch offers a rich set of configuration options:

Complete options can be viewed via fswatch --help.

Practical Application Example

The following script demonstrates monitoring the ~/Documents/processed directory and automatically processing new files:

#!/bin/bash
# process_new_files.sh

WATCH_DIR="~/Documents/processed"
SCRIPT_DIR="$(dirname "$0")"

fswatch -o "$WATCH_DIR" | while read num_events
do
    # Get the latest file
    latest_file=$(ls -t "$WATCH_DIR" | head -1)
    
    if [ -n "$latest_file" ]; then
        echo "Processing new file: $latest_file"
        # Execute actual processing logic
        "$SCRIPT_DIR/process_file.sh" "$WATCH_DIR/$latest_file"
    fi
done

launchd: System-Level Monitoring Solution

As macOS's system service management framework, launchd provides an alternative file monitoring approach. Through XML configuration files, monitoring rules can be defined, making it suitable for scenarios requiring system-level persistent monitoring.

Basic Configuration Example

Create ~/Library/LaunchAgents/com.example.monitor.plist:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.example.monitor</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/bin/logger</string>
        <string>Path modified</string>
    </array>
    <key>WatchPaths</key>
    <array>
        <string>/Users/username/Desktop/</string>
    </array>
</dict>
</plist>

Service Management

Load the monitoring service:

launchctl load ~/Library/LaunchAgents/com.example.monitor.plist

Unload the service:

launchctl unload ~/Library/LaunchAgents/com.example.monitor.plist

Technical Comparison and Selection Recommendations

Advantages of fswatch:

Advantages of launchd:

Selection recommendation: fswatch is recommended for development environments, while launchd can be considered for production environments or scenarios requiring system services.

Performance Optimization Suggestions

  1. Set Appropriate Latency: Use the -l parameter to adjust event collection latency, balancing real-time performance and system load
  2. Path Filtering: Exclude irrelevant directories via -e to reduce event volume
  3. Avoid Deep Recursion: Avoid using -r unnecessarily, or limit monitoring directory depth
  4. Batch Processing: Combine -o and xargs for batch event processing to reduce script invocation overhead

Common Issues and Solutions

Issue 1: fswatch produces no output or responds with delay

Solution: Check path permissions, use the -v parameter to enable verbose output for debugging. Ensure the monitored path exists and is accessible.

Issue 2: Script execution permission problems

Solution: Ensure the processing script has execution permissions (chmod +x script.sh) and specify the interpreter at the script's beginning (#!/bin/bash).

Issue 3: launchd service fails to start

Solution: Check plist file syntax using plutil -lint file.plist for validation. Ensure WatchPaths paths are correct.

Conclusion

File system monitoring on macOS can be achieved through two solutions: fswatch and launchd. fswatch, with its flexibility and real-time performance, is the preferred choice for development, while launchd is more suitable for system-level monitoring needs. Understanding the principles and applicable scenarios of both tools enables developers to build efficient and reliable file monitoring systems.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.