fswatch

Example monitoring a directory and capturing events with fswatch after 5000 files were moved to that directory. Interesting observation that while this worked well for 5000 files it did not work well for 100 files (not all events were caught all the time).

Bash Code
# shellcheck disable=SC2002
# shellcheck disable=SC2155
# shellcheck disable=SC2034

export date_now="$(date.now)"
export MONITORED_DIR="/tmp/fswatch_example/${date_now:?}/monitored_dir"
export STAGING_DIR="/tmp/fswatch_example/${date_now:?}/staging_dir"
export OUT_FILE="/tmp/fswatch_example/${date_now:?}/out.txt"
export HOW_MANY_FILES_TO_TEST="1000"
export MAX_TIME_TO_WAIT_MILLIS="10000"

sleep_until_all_events_or_we_timed_out(){
  local millis_stamp=$(millis.stamp)

  while [[ "$(millis.passed_since_stamp "${millis_stamp:?}")" -lt "${MAX_TIME_TO_WAIT_MILLIS:?}" ]]; do
    local actual_captured="$(cat "${OUT_FILE:?}" | wc -l)"
     if [[ "${actual_captured:?}" -eq "${HOW_MANY_FILES_TO_TEST:?}" ]]; then
       break
     fi
     echo.log "Sleeping 0.5 seconds, Events captured=${actual_captured:?}/${HOW_MANY_FILES_TO_TEST:?}..."
     sleep 0.5
  done

  millis.passed_since_stamp "${millis_stamp:?}"
}

_recreate_dir(){
  local dir="${1:?dir}"

  ei rm -rf "${dir:?}"
  ei mkdir -p "${dir:?}"
}

_populate_staging_dir(){
    echo.log "Starting to write ${HOW_MANY_FILES_TO_TEST:?} to ${STAGING_DIR:?}"
    # Write HOW_MANY_FILES_TO_TEST files to the staging DIR
    for i in $(seq 1 ${HOW_MANY_FILES_TO_TEST:?}); do
      echo "content-${i:?}" > "${STAGING_DIR:?}/file_${i:?}.txt" || throw "Failed write of file."
    done
    echo.log "Wrote ${HOW_MANY_FILES_TO_TEST} files to ${STAGING_DIR}"
}
main() {
    install_if_missing fswatch

    _recreate_dir "${MONITORED_DIR:?}"
    _recreate_dir "${STAGING_DIR:?}"
    echo.log "Recreated ${MONITORED_DIR} and ${STAGING_DIR}"

    _populate_staging_dir

    # Start fswatch in the background to monitor MONITORED_DIR and write to OUT_FILE
    echo.log "Starting fswatch on ${MONITORED_DIR}, putting it as background process..."
    fswatch "${MONITORED_DIR}" > "${OUT_FILE}" &
    FSWATCH_PID=$!

    echo.log "Move files from ${STAGING_DIR:?} to ${MONITORED_DIR} DIR..."
    ei mv "${STAGING_DIR:?}"/* "${MONITORED_DIR:?}/"

    local millis_passed_since_stamp=$(sleep_until_all_events_or_we_timed_out)

    # Stop fswatch
    kill "${FSWATCH_PID}"

    # Display results
    local actual_captured="$(cat "${OUT_FILE:?}" | sort | uniq | wc -l)"
    echo "Events written to ${OUT_FILE}"

    if [[ "${actual_captured:?}" -eq "${HOW_MANY_FILES_TO_TEST:?}" ]]; then
        echo.green "Captured all ${actual_captured:?} expected events. Took ${millis_passed_since_stamp:?} milliseconds."
    else
        echo.yellow "Captured ${actual_captured:?}/${HOW_MANY_FILES_TO_TEST:?} expected events."
    fi
}

main "${@}" || exit 1


Backlinks