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

问题描述 投票:58回答:11

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

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

linux shell inotify
11个回答
22
投票

使用inotify-tools


0
投票

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

使用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扩展名很有用。

更新:更好的是,制作一个alias并摆脱文件:

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

26
投票

我使用此脚本在目录树中的更改上运行构建脚本:

#!/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。检查inotifywait man page如何自定义触发构建的内容。


18
投票

您可以尝试使用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

3
投票

查看内核文件系统监视器守护程序

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

这是一个方法:

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


2
投票

如上所述,inotify-tools可能是最好的主意。但是,如果您正在编程以获得乐趣,您可以通过明智地应用tail -f来尝试获取黑客XP。


2
投票

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

1
投票

这是另一种选择:http://fileschanged.sourceforge.net/

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


1
投票

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

0
投票

出于调试目的,当我编写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上测试,对于Mac OS,将ls行更改为:

"$(ls -lT $file | awk '{ print $8 }')"
© www.soinside.com 2019 - 2024. All rights reserved.