web-dev-qa-db-ja.com

ファイルまたはディレクトリが変更されたときにシェルスクリプトを実行する方法

特定のファイルまたはディレクトリが変更されたときにシェルスクリプトを実行したい。

どうすれば簡単にできますか?

57
Drew LeSueur

inotify-tools を使用します。

22

このスクリプトを使用して、ディレクトリツリーの変更に対してビルドスクリプトを実行します。

#!/bin/bash -eu
DIRECTORY_TO_OBSERVE="js"      # might want to change this
function block_for_change {
  inotifywait --recursive \
    --event modify,move,create,delete \
    $DIRECTORY_TO_OBSERVE
}
BUILD_SCRIPT=build.sh          # might want to change this too
function build {
  bash $BUILD_SCRIPT
}
build
while block_for_change; do
  build
done

inotify-toolsを使用します。ビルドをトリガーするものをカスタマイズする方法については、inotifywaitmanページ を確認してください。

26

entr ツールを試して、ファイルが変更されたときに任意のコマンドを実行できます。ファイルの例:

$ ls -d * | entr sh -c 'make && make test'

または:

$ ls *.css *.html | entr reload-browser Firefox

または、ファイルChanged!が保存されたときにfile.txtを印刷します。

$ echo file.txt | entr echo Changed!

ディレクトリには-dを使用しますが、ループ内で使用する必要があります。例:

while true; do find path/ | entr -d echo Changed; done

または:

while true; do ls path/* | entr -pd echo Changed; done
18
kenorb

カーネルファイルシステムモニターデーモンを確認する

http://freshmeat.net/projects/kfsmd/

方法は次のとおりです。

http://www.linux.com/archive/feature/1249

3
Brian Clements

前述したように、inotify-toolsはおそらく最良のアイデアです。ただし、楽しみのためにプログラミングしている場合は、 tail -f を適切に適用することで、ハッカーXPを獲得できます。

2
Yoric

このスクリプトはどうですか? 'stat'コマンドを使用してファイルのアクセス時間を取得し、アクセス時間に変更があるたびに(ファイルにアクセスするたびに)コマンドを実行します。

#!/bin/bash

while true

do

   ATIME=`stat -c %Z /path/to/the/file.txt`

   if [[ "$ATIME" != "$LTIME" ]]

   then

       echo "RUN COMMNAD"
       LTIME=$ATIME
   fi
   sleep 5
done
2
VDR

別のオプションを次に示します。 http://fileschanged.sourceforge.net/

特に「ディレクトリを監視し、新規または変更されたファイルをアーカイブする」「例4」を参照してください。

1
slowdog

inotifywaitで満足できます。

一般的なサンプルを次に示します。

inotifywait -m /path -e create -e moved_to -e close_write | # -m is --monitor, -e is --event
    while read path action file; do
        if [[ "$file" =~ .*rst$ ]]; then             # if suffix is '.rst'
            echo ${path}${file} ': '${action}        # execute your command
            echo 'make html'
            make html
        fi
    done
1
pwxcoo

デバッグのためだけに、シェルスクリプトを記述し、保存時に実行する場合、これを使用します。

#!/bin/bash
file="$1" # Name of file
command="${*:2}" # Command to run on change (takes rest of line)
t1="$(ls --full-time $file | awk '{ print $7 }')" # Get latest save time
while true
do
  t2="$(ls --full-time $file | awk '{ print $7 }')" # Compare to new save time
  if [ "$t1" != "$t2" ];then t1="$t2"; $command; fi # If different, run command
  sleep 0.5
done

として実行

run_on_save.sh myfile.sh ./myfile.sh arg1 arg2 arg3

編集:Ubuntu 12.04でテスト済み、Mac OSの場合、ls行を次のように変更します。

"$(ls -lT $file | awk '{ print $8 }')"
0
jonatan

以下を〜/ .bashrcに追加します。

function react() {
    if [ -z "$1" -o -z "$2" ]; then
        echo "Usage: react <[./]file-to-watch> <[./]action> <to> <take>"
    Elif ! [ -r "$1" ]; then
        echo "Can't react to $1, permission denied"
    else
        TARGET="$1"; shift
        ACTION="$@"
        while sleep 1; do
            ATIME=$(stat -c %Z "$TARGET")
            if [[ "$ATIME" != "${LTIME:-}" ]]; then
                LTIME=$ATIME
                $ACTION
            fi
        done
    fi
}
0
Dan Garthwaite

inotifywaitの使用例

関連ファイルを変更するたびにRails testを実行したいとします。

1。監視したい関連ファイルのリストを作成します:

手動で行うこともできますが、ackはそのリストを作成するのに非常に役立ちます。

ack --type-add=Rails:ext:rb,erb --Rails -f > Inotifyfile

2。 inotifywaitにジョブを実行するよう依頼します

while inotifywait --fromfile Inotifyfile; do Rails test; done

それでおしまい!

注:Vagrantを使用してVMでコードを実行する場合、 mhallin/vagrant-notify-forwarder 拡張機能が役立つ場合があります。

UPDATE:さらに良いのは、aliasを作成してファイルを削除することです:

alias rtest="while inotifywait $(ack --type-add=Rails:ext:rb,erb --Rails -f | tr \\n \ ); do Rails test; done"
0
Is Ma