在Linux中,如何在文件或目录更改时运行shell脚本

我想在特定文件或目录更改时运行一个shell脚本。

我怎么能轻松地做到这一点?

使用inotify-tools 。

我使用这个脚本来对目录树中的更改运行构build脚本:

#! /bin/bash DIRECTORY_TO_OBSERVE="js" // might want to change this function block_for_change { inotifywait -r \ -e 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 。 检查inotifywait 手册页以了解如何自定义触发构build的内容。

当文件改变时,你可以尝试使用工具来运行任意命令。 文件示例:

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

要么:

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

对于目录使用-d ,但你必须在循环中使用它,例如:

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

要么:

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

检查内核文件系统监视器守护进程

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

这是一个如何做到:

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

如前所述,inotify-tools可能是最好的主意。 但是,如果您为了获得乐趣而进行编程,则可以通过审慎地应用tail -f来尝试获得黑客XP。

这是另一个选项: http : //fileschanged.sourceforge.net/

特别参见“示例4”,其中“监视目录并存档任何新的或更改的文件”。

只是为了debugging目的,当我编写一个shell脚本,并希望它运行保存,我使用这个:

 #!/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上testing,对于Mac OS,将ls行更改为:

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

将以下内容添加到〜/ .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 } 

这个脚本怎么样? 使用“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