cat-file-watcher - Cat is watching your file -
ファイル変更監視ツール - ファイルの変更を検知してコマンドを実行
※このドキュメントは大部分がAI生成です。issueをagentに投げて生成させました。一部(コンセプト、使い分け、test)は人力で書いています
Quick Links
| 項目 | リンク | |——|——–| | 📊 開発状況 | generated-docs/development-status |
概要
ファイルのタイムスタンプの変更を監視し、ファイルが更新されたときにコマンドを実行するファイル監視ツールです。
特徴
- 複数のファイルを同時に監視
- ファイル変更時にカスタムコマンドを実行
- TOML設定ファイルで設定可能
- 軽量で使いやすい
- Windowsで、起動したアプリにフォーカスを奪われない(厳密にはすぐ奪い返す)設定可
インストール
- このリポジトリをクローン:
git clone https://github.com/cat2151/cat-file-watcher.git cd cat-file-watcher - 依存パッケージをインストール:
pip install -r requirements.txt
クイックスタート
最小限の設定で今すぐ始めましょう!たった1行のTOMLファイルで動作します:
- 設定ファイルを作成(
config.toml):files = [{path = "test.txt", command = "echo ファイルが変更されました"}] - 監視対象のファイルを作成:
touch test.txt - ファイルウォッチャーを起動:
python -m src --config-filename config.toml
これだけで、test.txt の変更を監視し、変更があればコマンドを実行します!
ファイルを編集してみてください:
echo "テスト" >> test.txt
コンソールに「ファイルが変更されました」と表示されます。
ポイント: 上記の1行形式は、インライン配列表記を使ったTOMLの正式な記法です。より読みやすい複数行形式も使えます(詳細は設定セクションを参照)。
使い方
設定ファイルを指定してファイルウォッチャーを実行:
python -m src --config-filename config.toml
引数:
--config-filename: TOML設定ファイルのパス(必須)
設定
監視するファイルと実行するコマンドを定義するTOML設定ファイルを作成します:
# デフォルトの監視間隔
# 時間フォーマット: "1s"(1秒)、"2m"(2分)、"3h"(3時間)、"0.5s"(0.5秒)
default_interval = "1s"
# 設定ファイル自体の変更チェック間隔
config_check_interval = "1s"
# コマンド実行ログのファイルパス(省略可)
log_file = "command_execution.log"
# エラーログのファイルパス(省略可)
# error_log_file = "error.log"
# コマンド実行抑制ログのファイルパス(省略可)
# suppression_log_file = "suppression.log"
# 時間帯の定義(省略可)
[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" }
設定フォーマット
設定ファイルには、各エントリがファイル名とコマンドをマッピングする [files] セクションが必要です:
- キー: 監視するファイルまたはディレクトリのパス(相対パスまたは絶対パス)
- ファイルの場合: ファイルの変更時刻が変わったときにコマンドを実行
- ディレクトリの場合: ディレクトリの変更時刻が変わったとき(ファイルの追加・削除など)にコマンドを実行
- 値: 実行するシェルコマンドを含む
commandフィールドを持つオブジェクトcommand(必須): ファイルまたはディレクトリ変更時に実行するシェルコマンドinterval(省略可): このファイルまたはディレクトリの監視間隔。時間フォーマット(”1s”, “2m”, “3h”, “0.5s”)で指定します。小数点も使用可能です(例: “0.5s”は0.5秒)。省略した場合はdefault_intervalが使用されますsuppress_if_process(省略可): 実行中のプロセス名にマッチする正規表現パターン。マッチするプロセスが見つかった場合、コマンド実行をスキップします。エディタなどの特定のプログラムが実行中の場合にアクションをトリガーしないようにする場合に便利ですtime_period(省略可): ファイルまたはディレクトリを監視する時間帯の名前。[time_periods]セクションで定義された時間帯名を指定します。指定した時間帯内でのみ監視しますenable_log(省略可):trueに設定すると、コマンド実行の詳細をログファイルに記録します(デフォルト:false)。グローバル設定でlog_fileの設定が必要ですcwd(省略可): コマンドを実行する前に指定されたパスに作業ディレクトリを変更します。これにより、コマンド内の相対パスが指定されたディレクトリから解決されますno_focus(省略可):trueに設定すると、フォーカスを奪わずにコマンドを実行します(デフォルト:false)。Windows専用 - コマンドは非同期で起動され(ツールは完了を待機しません)、ウィンドウは表示されますがアクティブ化されないため、フォーカスの奪取を防ぎます。shell=Falseを使用し、コマンドをスペースで分割します。Windows以外のプラットフォームでは、警告を表示して通常実行にフォールバックします。注意: パイプ、リダイレクト、環境変数展開などのシェル機能はこのモードでは使用できません
グローバル設定
default_interval(省略可): すべてのファイルおよびディレクトリのデフォルト監視間隔。時間フォーマット(”1s”, “2m”, “3h”, “0.5s”)で指定します。小数点も使用可能です(例: “0.5s”は0.5秒)。省略した場合は”1s”(1秒)が使用されますconfig_check_interval(省略可): 設定ファイル自体の変更チェック間隔。時間フォーマット(”1s”, “2m”, “3h”, “0.5s”)で指定します。設定ファイルが変更されると自動的に再読み込みされます。省略した場合は”1s”(1秒)が使用されますlog_file(省略可): コマンド実行の詳細を記録するログファイルのパス。設定すると、enable_log = trueが指定されたファイルまたはディレクトリのコマンド実行情報(タイムスタンプ、パス、TOML設定内容)がこのファイルに記録されますerror_log_file(省略可): コマンド実行エラーの詳細を記録するエラーログファイルのパス。設定すると、コマンド失敗時のエラーメッセージ、実行コマンド、標準エラー出力、スタックトレースなどの詳細情報がこのファイルに記録されますsuppression_log_file(省略可): コマンド実行抑制の詳細を記録するログファイルのパス。設定すると、suppress_if_processによりコマンド実行がスキップされた際の情報(タイムスタンプ、ファイルパス、プロセスパターン、マッチしたプロセス)がこのファイルに記録されます
時間帯設定
[time_periods] セクション(省略可)で時間帯を定義できます:
- 各時間帯は名前を付けて定義します
start: 開始時刻(HH:MM形式、例: “09:00”)end: 終了時刻(HH:MM形式、例: “17:00”)- 日をまたぐ時間帯もサポート(例:
start = "23:00", end = "01:00") - ファイルごとに
time_periodパラメータで時間帯名を指定すると、その時間帯内でのみそのファイルまたはディレクトリを監視します
例:
[time_periods]
business_hours = { start = "09:00", end = "17:00" } # 通常の時間帯
night_shift = { start = "23:00", end = "01:00" } # 日をまたぐ時間帯
設定例
様々なユースケースの完全な例は examples/config.example.toml を参照してください。
# デフォルトの監視間隔を1秒に設定
default_interval = "1s"
# 設定ファイル自体の変更チェック間隔を1秒に設定
config_check_interval = "1s"
# コマンド実行の詳細を記録するログファイル(省略可)
log_file = "command_execution.log"
# エラーログファイル(省略可)
# error_log_file = "error.log"
# コマンド実行抑制ログファイル(省略可)
# suppression_log_file = "suppression.log"
# 時間帯の定義
[time_periods]
business_hours = { start = "09:00", end = "17:00" }
after_hours = { start = "18:00", end = "08:00" } # 日をまたぐ
[files]
# デフォルト間隔を使用(1秒ごとにチェック)
"document.txt" = { command = "cp document.txt document.txt.bak" }
# カスタム間隔を指定(0.5秒ごとにチェック)
"app.log" = { command = "notify-send 'Log Updated' 'New entries in app.log'", interval = "0.5s" }
# カスタム間隔を指定(5秒ごとにチェック)
"config.ini" = { command = "systemctl reload myapp", interval = "5s" }
# 営業時間のみ監視
"report.txt" = { command = "python generate_report.py", time_period = "business_hours" }
# 営業時間外のみ監視(バッチ処理など)
"batch.csv" = { command = "./process_batch.sh", time_period = "after_hours" }
# 重要なファイルのログを有効化(タイムスタンプ、ファイルパス、設定内容を記録)
"important.txt" = { command = "backup.sh", enable_log = true }
動作の仕組み
- ツールがTOML設定ファイルを読み込みます
- 指定されたすべてのファイルの更新タイムスタンプを監視します
- ファイルのタイムスタンプが変更されると、関連するコマンドを実行します
- 設定ファイル自体も監視し、変更があれば自動的に再読み込みします
- このプロセスはCtrl+Cで停止するまで継続的に繰り返されます
コマンド実行の処理方式
重要: コマンドは順次実行(シーケンシャル)されます。
- ファイルの変更を検知してコマンドを実行する際、そのコマンドが完了(またはフォアグラウンド実行の場合は30秒のタイムアウト)するまで、次のファイルのチェックは行われません
- 例えば、あるファイルのコマンドが25秒かかる場合、その25秒間は他のファイルの監視は一時停止します
- この間に他のファイルが更新されても、実行中のコマンドが完了するまで検知されません(コマンド完了後、次のメインループで検知されます)
- 現在の実装では、複数ファイルの監視・実行を並列化する機能はサポートされていません
長時間実行が必要なコマンドの場合は、コマンド内でバックグラウンド実行するか、別プロセスで起動する工夫が必要です。
ノンブロッキング実行の方法:
- Linux/macOS: コマンドの末尾に
&を付ける(例:command = "long_task.sh &") - Windows: コマンドの先頭に
startを付ける(例:command = "start long_task.bat")
コマンド実行時の出力
実行されたコマンドの標準出力および標準エラー出力は、リアルタイムでコンソールに表示されます:
- 出力表示: コマンドの標準出力と標準エラー出力は、実行中に逐次コンソールに表示されます。長時間実行されるコマンドでも、途中経過をリアルタイムで確認できます
- 失敗時: コマンドが失敗した場合(終了コード 0以外)、
Error: Command failed for '<ファイルパス>' with exit code <コード>というメッセージが表示されます - エラーログファイル:
error_log_fileを設定している場合、コマンド失敗時のエラーメッセージと実行コマンドがログファイルに記録されます
フォアグラウンドで実行されるコマンドのタイムアウトは30秒に設定されており、それを超えるとタイムアウトエラーが発生します。長時間実行が必要なコマンドの場合は、バックグラウンド実行(& を使用)してください。バックグラウンド実行されたコマンドは、subprocess.run()が即座に完了するため、タイムアウトの制限を受けません。
コンセプト
toml記述内容がシンプルでメンテしやすいことを優先します
使い分け
手軽にファイル更新監視したい場合、楽に運用したい場合は、cat-file-watcher
散在するファイルを手早く更新監視on/offしたい場合は、cat-file-watcher
これにしかない各種機能を利用したい場合は、cat-file-watcher
もっと高度な機能を使いたい場合は、ほかのアプリ
TypeScriptアプリ開発等には、スタンダードにタスクランナー
開発
環境構築
開発環境のセットアップ:
# 依存パッケージのインストール(実行環境用)
pip install -r requirements.txt
# 開発用依存パッケージのインストール(Ruffを含む)
pip install -r dev-requirements.txt
コード品質チェック
このプロジェクトでは、コード品質を保つためにRuffを使用しています。
Ruffの実行
# リンターチェック
ruff check src/
# 自動修正可能な問題を修正
ruff check --fix src/
# コードフォーマットのチェック
ruff format --check src/
# コードフォーマットを適用
ruff format src/
テストの実行
# 全テストの実行
pytest
# 詳細出力付きでテストを実行
pytest -v
- Linux
- テストはすべてLinux用です。
- GitHub Copilot Coding Agentが、 GitHub Actions(Linux Runner)上でテストコードを生成し TDDしたものです。
- Windows
- Windows環境でWSL2を使わずテストをするとtest redが多発します。これはテストがLinux用であるためです。
- Windows環境でテストするには、WSL2を使います。
- 具体的には、WSL2をinstallして、
wsl pip install -r dev-requirements.txtで準備してから、wsl pytestします。 - WSL2だといくつかtest redになることがありますが許容しています。issueをagentに投げたときTDDしてtest greenであればOK、を基準としています。
ライセンス
MIT License - 詳細はLICENSEファイルを参照してください
※英語版README.mdは、README.ja.mdを元にGeminiの翻訳でGitHub Actionsにより自動生成しています
Big Brother watched your files. Now the cat does. 🐱