Skip to content

File Change Monitoring Tool - Detects file changes and executes commands

License

Notifications You must be signed in to change notification settings

cat2151/cat-file-watcher

Repository files navigation

cat-file-watcher - Cat is watching your file -

File Change Monitoring Tool - Detects file changes and executes commands

Japanese English Ask DeepWiki

Note: This document is largely AI-generated. It was generated by submitting issues to an agent. Some sections (concept, usage distinction, tests) were written manually.

Quick Links

Item Link
📊 Development Status generated-docs/development-status

Overview

This is a file monitoring tool that watches for changes in file timestamps and executes commands when files are updated.

Features

  • Monitor multiple files simultaneously
  • Execute custom commands on file changes
  • Configurable via TOML configuration file
  • Lightweight and easy to use
  • On Windows, can be configured to prevent launched applications from stealing focus (or quickly reclaim it).

Installation

  1. Clone this repository:
git clone https://github.com/cat2151/cat-file-watcher.git
cd cat-file-watcher
  1. Install dependencies:
pip install -r requirements.txt

Quick Start

Get started immediately with minimal setup! It works with just one line in a TOML file:

  1. Create a configuration file (config.toml):
files = [{path = "test.txt", command = "echo ファイルが変更されました"}]
  1. Create the file to be monitored:
touch test.txt
  1. Start the file watcher:
python -m src --config-filename config.toml

That's it! This will monitor changes to test.txt and execute a command if it changes!

Try editing the file:

echo "テスト" >> test.txt

You will see "ファイルが変更されました" printed to the console.

Note: The single-line format above is a formal TOML notation using inline array representation. A more readable multi-line format is also available (see the Configuration section for details).

Usage

Run the file watcher by specifying a configuration file:

python -m src --config-filename config.toml

Arguments:

  • --config-filename: Path to the TOML configuration file (required)

Configuration

Create a TOML configuration file to define files to watch and commands to execute:

# Default monitoring interval
# Time format: "1s" (1 second), "2m" (2 minutes), "3h" (3 hours), "0.5s" (0.5 seconds)
default_interval = "1s"

# Check interval for the configuration file itself
config_check_interval = "1s"

# File path for command execution logs (optional)
log_file = "command_execution.log"

# File path for error logs (optional)
# error_log_file = "error.log"

# File path for command suppression logs (optional)
# suppression_log_file = "suppression.log"

# Time period definitions (optional)
[time_periods]
business_hours = { start = "09:00", end = "17:00" }
night_shift = { start = "23:00", end = "01:00" }

[files]
"myfile.txt" = { command = "echo 'File changed!'" }
"script.py" = { command = "python -m pytest tests/", interval = "2s" }
"src/main.py" = { command = "make build", suppress_if_process = "vim|emacs|code" }
"batch.csv" = { command = "./process.sh", time_period = "night_shift" }
"important.txt" = { command = "backup.sh", enable_log = true }
"lib/module.c" = { command = "gcc -c module.c -o module.o", cwd = "./lib" }

Configuration Format

The configuration file requires a [files] section where each entry maps a file name to a command:

  • Key: Path to the file or directory to monitor (relative or absolute path)
    • For files: Executes a command when the file's modification time changes
    • For directories: Executes a command when the directory's modification time changes (e.g., file addition/deletion)
  • Value: An object containing either a command field for the shell command to execute (normal mode), or an argv field (no_focus mode).
    • command (required in normal mode): The shell command to execute when the file or directory changes. Note: Cannot be used if no_focus=true is set.
    • argv (required in no_focus mode): A required array field when no_focus=true. Specifies the executable name and arguments as an array. Example: argv = ["notepad.exe", "file.txt"].
    • interval (optional): The monitoring interval for this file or directory. Specify in time format ("1s", "2m", "3h", "0.5s"). Decimal values are also allowed (e.g., "0.5s" for 0.5 seconds). If omitted, default_interval will be used.
    • suppress_if_process (optional): A regular expression pattern to match against running process names. If a matching process is found, command execution is skipped. This is useful for preventing actions from being triggered when certain programs, such as editors, are running.
    • time_period (optional): The name of the time period during which the file or directory should be monitored. Specify a time period name defined in the [time_periods] section. Monitoring will only occur within the specified time period.
    • enable_log (optional): If set to true, details of command execution will be logged to a log file (default: false). The log_file setting must be configured in global settings.
    • cwd (optional): Changes the working directory to the specified path before executing the command. This ensures that relative paths within the command are resolved from the specified directory.
    • no_focus (optional): If set to true, the command will be executed without stealing focus (default: false). Windows only - The command is launched asynchronously (the tool does not wait for completion), and the window will be displayed but not activated, preventing focus capture. Uses shell=False. On non-Windows platforms, a warning will be displayed and it will fall back to normal execution. Important: If no_focus=true, the command field cannot be used; instead, the argv array field is required. Example: argv = ["notepad.exe", "file.txt"].

Global Settings

  • default_interval (optional): The default monitoring interval for all files and directories. Specify in time format ("1s", "2m", "3h", "0.5s"). Decimal values are also allowed (e.g., "0.5s" for 0.5 seconds). If omitted, "1s" (1 second) will be used.
  • config_check_interval (optional): The interval for checking changes to the configuration file itself. Specify in time format ("1s", "2m", "3h", "0.5s"). The configuration file will be automatically reloaded if it changes. If omitted, "1s" (1 second) will be used.
  • log_file (optional): Path to the log file for recording command execution details. If set, command execution information (timestamp, path, TOML configuration content) for files or directories with enable_log = true will be recorded in this file.
  • error_log_file (optional): Path to the error log file for recording command execution error details. If set, detailed information such as error messages, executed commands, standard error output, and stack traces on command failure will be recorded in this file.
  • suppression_log_file (optional): Path to the log file for recording command execution suppression details. If set, information (timestamp, file path, process pattern, matched process) when command execution is skipped due to suppress_if_process will be recorded in this file.

Time Period Settings

You can define time periods in the optional [time_periods] section:

  • Each time period is defined with a name.
  • start: Start time (HH:MM format, e.g., "09:00")
  • end: End time (HH:MM format, e.g., "17:00")
  • Time periods spanning across midnight are also supported (e.g., start = "23:00", end = "01:00")
  • By specifying a time period name with the time_period parameter for each file, that file or directory will only be monitored within that time period.

Example:

[time_periods]
business_hours = { start = "09:00", end = "17:00" }  # Normal business hours
night_shift = { start = "23:00", end = "01:00" }     # Time period spanning midnight

Configuration Example

For a complete example covering various use cases, refer to examples/config.example.toml.

# Set default monitoring interval to 1 second
default_interval = "1s"

# Set configuration file change check interval to 1 second
config_check_interval = "1s"

# Log file for command execution details (optional)
log_file = "command_execution.log"

# Error log file (optional)
# error_log_file = "error.log"

# Command suppression log file (optional)
# suppression_log_file = "suppression.log"

# Time period definitions
[time_periods]
business_hours = { start = "09:00", end = "17:00" }
after_hours = { start = "18:00", end = "08:00" }  # Spans across midnight

[files]
# Use default interval (checks every 1 second)
"document.txt" = { command = "cp document.txt document.txt.bak" }

# Specify custom interval (checks every 0.5 seconds)
"app.log" = { command = "notify-send 'Log Updated' 'New entries in app.log'", interval = "0.5s" }

# Specify custom interval (checks every 5 seconds)
"config.ini" = { command = "systemctl reload myapp", interval = "5s" }

# Monitor only during business hours
"report.txt" = { command = "python generate_report.py", time_period = "business_hours" }

# Monitor only outside business hours (e.g., for batch processing)
"batch.csv" = { command = "./process_batch.sh", time_period = "after_hours" }

# Enable logging for important files (records timestamp, file path, and configuration content)
"important.txt" = { command = "backup.sh", enable_log = true }

How It Works

  1. The tool reads the TOML configuration file.
  2. It monitors the modification timestamps of all specified files.
  3. When a file's timestamp changes, it executes the associated command.
  4. The configuration file itself is also monitored and automatically reloaded if it changes.
  5. This process continuously repeats until stopped with Ctrl+C.

Command Execution Handling

Important: Commands are executed sequentially.

  • When a file change is detected and a command is executed, the next file check will not occur until that command completes (or times out after 30 seconds for foreground execution).
  • For example, if a command for one file takes 25 seconds, monitoring of other files will be paused for those 25 seconds.
  • Even if other files are updated during this time, they will not be detected until the currently running command finishes (they will be detected in the next main loop after the command completes).
  • The current implementation does not support parallelizing the monitoring and execution for multiple files.

For commands that require long execution times, you need to implement background execution within the command or launch it as a separate process.

Methods for Non-Blocking Execution:

  • Linux/macOS: Append & to the end of the command (e.g., command = "long_task.sh &")
  • Windows: Prefix the command with start (e.g., command = "start long_task.bat")

Command Execution Output

The standard output and standard error of the executed command are displayed to the console in real-time:

  • Output Display: The standard output and standard error of the command are displayed sequentially to the console during execution. Even for long-running commands, real-time progress can be observed.
  • On Failure: If a command fails (exit code other than 0), a message like Error: Command failed for '<file path>' with exit code <code>` will be displayed.
  • Error Log File: If error_log_file is configured, error messages and executed commands upon command failure will be recorded in the log file.

Commands executed in the foreground have a timeout set to 30 seconds, beyond which a timeout error will occur. For commands that require longer execution, please use background execution (using &). Commands executed in the background are not subject to the timeout limit, as subprocess.run() completes immediately.

Concept

We prioritize simple and easily maintainable TOML descriptions.

Usage Scenarios

If you want to easily monitor file changes and operate with minimal effort, use cat-file-watcher.

If you want to quickly toggle file change monitoring on/off for scattered files, use cat-file-watcher.

If you want to utilize the various unique features it offers, use cat-file-watcher.

If you need more advanced features, consider other applications.

For TypeScript application development and similar tasks, use a standard task runner.

Development

Environment Setup

To set up the development environment:

# Install dependencies (for runtime environment)
pip install -r requirements.txt

# Install development dependencies (including Ruff)
pip install -r dev-requirements.txt

Code Quality Checks

This project uses Ruff to maintain code quality.

Running Ruff

# Linter check
ruff check src/

# Fix automatically fixable issues
ruff check --fix src/

# Check code format
ruff format --check src/

# Apply code format
ruff format src/

Running Tests

# Run all tests
pytest

# Run tests with verbose output
pytest -v
  • Linux

    • All tests are designed for Linux.
    • GitHub Copilot Coding Agent generated the test code and performed TDD on GitHub Actions (Linux Runner).
  • Windows

    • Running tests in a Windows environment without WSL2 will result in many test failures (test red) because the tests are designed for Linux.
    • To run tests in a Windows environment, use WSL2.
    • Specifically, install WSL2, then prepare by running wsl pip install -r dev-requirements.txt, and then execute wsl pytest.
    • Some tests might still fail (test red) even with WSL2, but this is acceptable. The criterion is that tests should be green when TDD was performed by submitting issues to the agent.

License

MIT License - See the LICENSE file for details

The English README.md is automatically generated by GitHub Actions using Gemini's translation based on README.ja.md.

Big Brother watched your files. Now the cat does. 🐱

About

File Change Monitoring Tool - Detects file changes and executes commands

Topics

Resources

License

Stars

Watchers

Forks

Contributors 3

  •  
  •  
  •  

Languages