当文件或目录发生更改时,如何运行shell脚本?

时间:2022-05-26 02:22:14

I want to run a shell script when a specific file or directory changes.

当特定文件或目录发生更改时,我希望运行shell脚本。

How can I easily do that?

我怎么能轻易做到呢?

9 个解决方案

#1


23  

Use inotify-tools.

使用inotify-tools。

#2


18  

I use this script to run a build script on changes in a directory tree:

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

#! /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

Uses inotify-tools. Check inotifywait man page for how to customize what triggers the build.

使用inotify-tools。检查inotifywait man页面,了解如何自定义触发构建的因素。

#3


11  

You may try entr tool to run arbitrary commands when files change. Example for files:

当文件发生变化时,您可以尝试使用entr工具来运行任意命令。文件的例子:

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

or:

或者:

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

For directories use -d, but you've to use it in the loop, e.g.:

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

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

or:

或者:

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

#4


3  

Check out the kernel filesystem monitor daemon

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

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

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

Here's a how-to:

这里有一个指南:

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

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

#5


2  

As mentioned, inotify-tools is probably the best idea. However, if you're programming for fun, you can try and earn hacker XPs by judicious application of tail -f .

如前所述,inotify-tools可能是最好的方法。但是,如果您是为了好玩而编程,您可以尝试通过明智地应用tail -f来获得黑客XPs。

#6


1  

Here's another option: http://fileschanged.sourceforge.net/

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

See especially "example 4", which "monitors a directory and archives any new or changed files".

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

#7


0  

How about this script? Uses the 'stat' command to get the access time of a file and runs a command whenever there is a change in the access time (whenever file is accessed).

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

#8


0  

Just for debugging purposes, when I write a shell script and want it to run on save, I use this:

出于调试目的,当我编写shell脚本并希望它在save上运行时,我使用以下方法:

#!/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 it as

运行它

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

Edit: Above tested on Ubuntu 12.04, for Mac OS, change the ls lines to:

编辑:以上在Ubuntu 12.04上测试过,对于Mac OS,将ls改为:

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

#9


0  

Add the following to ~/.bashrc:

向~/.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
}

#1


23  

Use inotify-tools.

使用inotify-tools。

#2


18  

I use this script to run a build script on changes in a directory tree:

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

#! /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

Uses inotify-tools. Check inotifywait man page for how to customize what triggers the build.

使用inotify-tools。检查inotifywait man页面,了解如何自定义触发构建的因素。

#3


11  

You may try entr tool to run arbitrary commands when files change. Example for files:

当文件发生变化时,您可以尝试使用entr工具来运行任意命令。文件的例子:

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

or:

或者:

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

For directories use -d, but you've to use it in the loop, e.g.:

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

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

or:

或者:

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

#4


3  

Check out the kernel filesystem monitor daemon

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

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

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

Here's a how-to:

这里有一个指南:

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

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

#5


2  

As mentioned, inotify-tools is probably the best idea. However, if you're programming for fun, you can try and earn hacker XPs by judicious application of tail -f .

如前所述,inotify-tools可能是最好的方法。但是,如果您是为了好玩而编程,您可以尝试通过明智地应用tail -f来获得黑客XPs。

#6


1  

Here's another option: http://fileschanged.sourceforge.net/

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

See especially "example 4", which "monitors a directory and archives any new or changed files".

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

#7


0  

How about this script? Uses the 'stat' command to get the access time of a file and runs a command whenever there is a change in the access time (whenever file is accessed).

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

#8


0  

Just for debugging purposes, when I write a shell script and want it to run on save, I use this:

出于调试目的,当我编写shell脚本并希望它在save上运行时,我使用以下方法:

#!/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 it as

运行它

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

Edit: Above tested on Ubuntu 12.04, for Mac OS, change the ls lines to:

编辑:以上在Ubuntu 12.04上测试过,对于Mac OS,将ls改为:

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

#9


0  

Add the following to ~/.bashrc:

向~/.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
}