Watchdog

Monitor a folder for adds, deletes, modifications; trigger actions and chain workflows

What is Watchdog?

Watchdog monitors activity in a specified folder and notices when items are added, deleted, modified, or moved. You can configure it to take actions in response, letting you chain a sequence of tasks into automated workflows.

pip install watchdog python-dotenv

How to use

  • Place the .py and .bat in the same folder with the same base name.
  • Edit the --input path in the .bat, or run without args to be prompted.
  • Optional: put a .env next to the files (or parent folders); the Python script will load it.
  • Remove both pause lines in the .bat to skip โ€œPress any key to continueโ€ฆโ€.

Python script (py_watchdog.py)

import argparse
import time
import os
from dotenv import load_dotenv
from pathlib import Path
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler

# ----- Load .env -----
def load_env_from_nearest():
    search_dirs = [Path(__file__).parent, Path(__file__).parent.parent, Path(__file__).parent.parent.parent]
    for directory in search_dirs:
        env_path = directory / ".env"
        if env_path.exists():
            load_dotenv(dotenv_path=env_path)
            print(f"๐Ÿ“ฆ Loaded .env from: {env_path}")
            return
    print("โš ๏ธ No .env file found.")

# ----- File system event handler -----
class LoggingEventHandler(FileSystemEventHandler):
    def on_created(self, event):
        print(f"[CREATE] {'๐Ÿ“' if event.is_directory else '๐Ÿ“„'} {event.src_path}")

    def on_deleted(self, event):
        print(f"[DELETE] {'๐Ÿ“' if event.is_directory else '๐Ÿ“„'} {event.src_path}")

    def on_modified(self, event):
        print(f"[MODIFY] {'๐Ÿ“' if event.is_directory else '๐Ÿ“„'} {event.src_path}")

    def on_moved(self, event):
        print(f"[MOVE]   {'๐Ÿ“' if event.is_directory else '๐Ÿ“„'} {event.src_path} โ†’ {event.dest_path}")

# ----- Main -----
def main():
    load_env_from_nearest()

    parser = argparse.ArgumentParser(description="Watch a folder and print file events.")
    parser.add_argument("--input", help="Folder to watch")
    args = parser.parse_args()

    folder_to_watch = args.input or input("Enter folder path to watch: ").strip()

    if not os.path.isdir(folder_to_watch):
        print("โŒ Invalid folder path.")
        return

    print(f"๐Ÿ‘€ Watching folder: {folder_to_watch}")
    print("Press Ctrl+C to stop.")

    event_handler = LoggingEventHandler()
    observer = Observer()
    observer.schedule(event_handler, path=folder_to_watch, recursive=False)
    observer.start()

    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        print("๐Ÿ›‘ Stopping watcher.")
        observer.stop()
    observer.join()

if __name__ == "__main__":
    main()

Launcher (.bat)

Doubleโ€‘click the .bat to run the matching .py (same base name) and pass --input. It loads .env if present in the same folder. Remove pause lines to skip โ€œPress any keyโ€ฆโ€.

@echo off
setlocal enabledelayedexpansion

REM Get current directory and base filename without extension
set "CURRENT_DIR=%~dp0"
set "BASE_NAME=%~n0"

REM Load environment variables from .env
if exist "%CURRENT_DIR%.env" (
    for /F "usebackq tokens=*" %%A in ("%CURRENT_DIR%.env") do set "%%A"
) else (
    echo Warning: .env file not found
)

echo Running %BASE_NAME%.py from %CURRENT_DIR%

REM Run Python script with same base name
python "%CURRENT_DIR%%BASE_NAME%.py" --input "T:\Render\watchdog"

REM Check for errors
if errorlevel 1 (
    echo Error: Failed to run %BASE_NAME%.py
    pause
    exit /b 1
) else (
    echo Success: %BASE_NAME%.py completed
)

pause