指定したファイルの更新があったらコマンドを自動実行するシェルスクリプト

プログラミングの作業をしていると、一旦コンパイルや実行を行なって結果を確認したくなることがあります。

C++Javaであればコンパイル -> 実行が必要ですし、rspecのようなコマンドでテストを行いたい場合もあると思います。

その度にエディタを終了-> (コンパイル実行 ->) 実行 -> またエディタを起動とかするのはとても手間です。(エディタ内でコンパイルとかするもありますが、それでも何らかのコマンドが必要です)

そこで、特定のファイルを監視下に入れてそのファイルの更新があったら指定されたコマンドを実行するようなシェルスクリプトを作ってみました。

#!/bin/sh
if [ $# -ne 2 ]; then
        echo "実行するには2個の引数が必要です。
        第一引数: 監視対象ファイル名
        第二引数: 監視対象ファイルが更新された際に実行されるコ>マンド
        例: ./autoexec.sh a.cpp 'g++ a.cpp && ./a.cpp'"
        exit 1
fi
echo "監視対象 $1"
echo "実行コマンド $2"
INTERVAL=1 #監視間隔, 秒で指定
last=`ls --full-time $1 | awk '{print $6"-"$7}'`
while true; do
        sleep $INTERVAL
        current=`ls --full-time $1 | awk '{print $6"-"$7}'`
        if [ $last != $current ] ; then
                echo ""
                echo "updated: $current"
                last=$current
                eval $2
        fi
done

第一引数で監視するファイルを第一引数で指定、第二引数に"javac a.cpp"のように実行したいコマンドを指定してください。

第一引数の監視対象ファイルに更新があると第二引数がトリガされます。
screenなんかで画面を分割して片側に表示させたりするといいかもしれません。

Mac (BSD) で使う場合、lsの引数体系がすこし違うので、こちらが使えます

#!/bin/sh
if [ $# -ne 2 ]; then
        echo "実行するには2個の引数が必要です。
        第一引数: 監視対象ファイル名
        第二引数: 監視対象ファイルが更新された際に実行されるコ>マンド
        例: ./autoexec.sh a.cpp 'g++ a.cpp && ./a.cpp'"
        exit 1
fi
echo "監視対象 $1"
echo "実行コマンド $2"
INTERVAL=1 #監視間隔, 秒で指定
last=`ls -l -T $1 | awk '{print $8}'`
while true; do
        sleep $INTERVAL
        current=`ls -l -T $1 | awk '{print $8}'`
        if [ $last != $current ] ; then
                echo ""
                echo "updated: $current"
                last=$current
                eval $2
        fi
done

不具合とかあったらご指摘ください。