Skip to content

Monitoring a Directory on Linux

Practical approaches for watching directory changes from a Linux system or service.

This English edition keeps the original illustrations and reproducible command or configuration examples.

Reference diagram 1

Reference diagram 2

Commands and configuration

bash复制代码# Debian/Ubuntu
sudo apt-get install inotify-tools

# CentOS/RHEL
sudo yum install inotify-tools
#!/bin/bash

# Function to display usage
usage() {
    echo "Usage: $0 <source_directory> <destination_directory> [--verbose]"
    exit 1
}

# Check if the correct number of arguments is passed
if [ $# -lt 2 ]; then
    usage
fi

# Get the arguments
SOURCE_DIR="$1"
DEST_DIR="$2"
VERBOSE=false

if [ "$3" == "--verbose" ]; then
    VERBOSE=true
fi

# Check if the source and destination directories exist
if [ ! -d "$SOURCE_DIR" ]; then
    echo "Error: Source directory $SOURCE_DIR does not exist."
    exit 1
fi

if [ ! -d "$DEST_DIR" ]; then
    echo "Error: Destination directory $DEST_DIR does not exist."
    exit 1
fi

# Function to print verbose messages
verbose_echo() {
    if $VERBOSE; then
        echo "$1"
    fi
}

# Check if inotify-tools is installed
if ! command -v inotifywait &> /dev/null; then
    echo "Warning: inotify-tools is not installed. Falling back to polling."
    FALLBACK=true
else
    FALLBACK=false
fi

# Sync logic for inotify
inotify_sync() {
    verbose_echo "Using inotify for directory monitoring..."
    inotifywait -m -r -e create,modify,delete "$SOURCE_DIR" --format '%w%f %e' | while read FILE EVENT; do
        RELATIVE_PATH="${FILE#$SOURCE_DIR/}"
        DEST_PATH="$DEST_DIR/$RELATIVE_PATH"

        case $EVENT in
            CREATE,ISDIR)
                verbose_echo "Directory created: $FILE"
                mkdir -p "$DEST_PATH"
                ;;
            CREATE|MODIFY)
                verbose_echo "File created or modified: $FILE"
                mkdir -p "$(dirname "$DEST_PATH")"
                cp "$FILE" "$DEST_PATH"
                ;;
            DELETE|DELETE,ISDIR)
                verbose_echo "File or directory deleted: $FILE"
                rm -rf "$DEST_PATH"
                ;;
        esac
    done
}

# Sync logic for fallback (polling)
polling_sync() {
    verbose_echo "Using polling method for directory monitoring..."
    TEMP_FILE="/tmp/prev_files.txt"

    # Initially record the current list of files and directories
    find "$SOURCE_DIR" -type f | sort > "$TEMP_FILE"

    while true; do
        CURRENT_FILES=$(find "$SOURCE_DIR" -type f | sort)

        if ! diff <(echo "$CURRENT_FILES") "$TEMP_FILE" > /dev/null; then
            verbose_echo "Changes detected, syncing..."
            rsync -av --delete "$SOURCE_DIR/" "$DEST_DIR/"
            echo "$CURRENT_FILES" > "$TEMP_FILE"
        fi

        sleep 0.5
    done
}

# Use appropriate method based on tool availability
if $FALLBACK; then
    polling_sync
else
    inotify_sync
fi
/folder_change_sync.sh /tmp/test /home/hywelstar/work/monitor/backup --verbose

Practical notes

Test each change on a recoverable target, keep logs from the boot or failure path, and record the exact kernel and userspace versions used in the result.