import time
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
import re
from pathlib import Path
from typing import List, Callable, Optional
class PatternFileMonitor(FileSystemEventHandler):
"""
Monitors file system events and filters them based on file patterns.
"""
def __init__(self, patterns: List[str], callback: Callable[[str, str], None]):
"""
Initialize the monitor with patterns and callback function.
Args:
patterns: List of file patterns to match (e.g., ['*.txt', '*.py'])
callback: Function to call when matching files are modified
Takes parameters (event_type, file_path)
"""
self.patterns = patterns
self.callback = callback
# Compile regex patterns for better performance
self.compiled_patterns = [re.compile(pattern.replace('*', '.*')) for pattern in patterns]
def matches_pattern(self, file_path: str) -> bool:
"""Check if file path matches any of the configured patterns."""
path = Path(file_path)
return any(pattern.match(path.name) for pattern in self.compiled_patterns)
def on_modified(self, event):
"""Handle file modification events."""
if not event.is_directory and self.matches_pattern(event.src_path):
self.callback("modified", event.src_path)
def on_created(self, event):
"""Handle file creation events."""
if not event.is_directory and self.matches_pattern(event.src_path):
self.callback("created", event.src_path)
def on_deleted(self, event):
"""Handle file deletion events."""
if not event.is_directory and self.matches_pattern(event.src_path):
self.callback("deleted", event.src_path)
def monitor_directory(
directory: str = ".",
patterns: List[str] = None,
recursive: bool = True,
callback: Optional[Callable[[str, str], None]] = None
):
"""
Monitor a directory for file changes matching specific patterns.
Args:
directory: Directory to monitor (default: current directory)
patterns: File patterns to watch (default: all files)
recursive: Whether to monitor subdirectories
callback: Custom function to handle events
"""
if patterns is None:
patterns = ["*"] # Match all files
if callback is None:
# Default callback function
def default_callback(event_type, file_path):
timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
print(f"[{timestamp}] {event_type.upper()}: {file_path}")
callback = default_callback
# Create event handler
event_handler = PatternFileMonitor(patterns, callback)
# Create observer
observer = Observer()
observer.schedule(event_handler, directory, recursive=recursive)
# Start monitoring
observer.start()
print(f"Monitoring {directory} for files matching: {patterns}")
print("Press Ctrl+C to stop...")
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
observer.stop()
print("\nMonitoring stopped.")
observer.join()
# Example usage with custom callback
def custom_file_handler(event_type: str, file_path: str):
"""Custom handler for specific file types."""
file_size = Path(file_path).stat().st_size if Path(file_path).exists() else 0
if event_type == "created":
print(f"π NEW FILE: {file_path} ({file_size} bytes)")
elif event_type == "modified":
print(f"βοΈ UPDATED: {file_path} ({file_size} bytes)")
elif event_type == "deleted":
print(f"ποΈ DELETED: {file_path}")
# Example: Monitor Python files in current directory
if __name__ == "__main__":
# Monitor only Python and text files in current directory
monitor_directory(
directory=".",
patterns=["*.py", "*.txt", "*.md"],
callback=custom_file_handler
)
This snippet implements a real-time file system monitor that watches for changes to files matching specific patterns. It uses the watchdog
library to efficiently track file system events (creation, modification, deletion) and filters them based on file name patterns.
*.py
, config.*
)File system monitoring is essential for many development and operational tasks:
pip install watchdog
# Monitor all files in current directory
monitor_directory()
# Monitor only Python files recursively
monitor_directory(patterns=["*.py"], recursive=True)
# Monitor specific directory with custom handler
monitor_directory("/path/to/dir", patterns=["*.log", "*.txt"], callback=my_handler)
def my_handler(event_type, file_path):
if event_type == "modified" and file_path.endswith(".py"):
print(f"Python file changed: {file_path}")
# Trigger automated testing, compilation, etc.
The script will run continuously until interrupted with Ctrl+C, providing real-time feedback on file system changes that match your criteria.