82

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

我怎样才能轻松做到这一点?

4

12 回答 12

56

您可以尝试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
于 2016-07-06T16:36:37.227 回答
34

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

#!/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 手册页以了解如何自定义触发构建的内容。

于 2013-12-04T16:57:15.997 回答
24

使用inotify-tools

链接的 Github 页面有许多示例;这是其中之一。

#!/bin/sh

cwd=$(pwd)

inotifywait -mr \
  --timefmt '%d/%m/%y %H:%M' --format '%T %w %f' \
  -e close_write /tmp/test |
while read -r date time dir file; do
       changed_abs=${dir}${file}
       changed_rel=${changed_abs#"$cwd"/}

       rsync --progress --relative -vrae 'ssh -p 22' "$changed_rel" \
           usernam@example.com:/backup/root/dir && \
       echo "At ${time} on ${date}, file $changed_abs was backed up via rsync" >&2
done
于 2010-10-30T19:08:53.103 回答
9

这个脚本怎么样?使用“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
于 2013-08-20T17:13:44.933 回答
3

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

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

这是一个操作方法:

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

于 2010-10-30T19:08:36.167 回答
2

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

于 2010-10-30T19:16:56.520 回答
2

仅出于调试目的,当我编写一个 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 }')"
于 2014-09-16T13:16:31.800 回答
2

将以下内容添加到 ~/.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
}
于 2015-10-15T14:45:30.633 回答
1

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

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

于 2010-10-30T19:19:26.523 回答
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
于 2019-02-17T08:43:41.010 回答
1

想要跟踪单个文件的鱼壳用户的快速解决方案:

while true
    set old_hash $hash
    set hash (md5sum file_to_watch)
    if [ $hash != $old_hash ]
        command_to_execute
    end
    sleep 1
end

在 macos 上替换md5sum为if 。md5

于 2021-10-18T10:00:11.990 回答
0

假设您想在rake test每次修改app/test/目录中的任何 ruby​​ 文件(“*.rb”)时运行。

只需获取观看文件的最新修改时间,并检查该时间是否已更改。

脚本代码

t_ref=0; while true; do t_curr=$(find app/ test/ -type f -name "*.rb" -printf "%T+\n" | sort -r | head -n1); if [ $t_ref != $t_curr ]; then t_ref=$t_curr; rake test; fi; sleep 1; done

好处

  • 当文件更改时,您可以运行任何命令或脚本。
  • 它适用于任何文件系统和虚拟机(VirtualBox 上使用 Vagrant 的共享文件夹);例如,您可以在 Macbook 上使用文本编辑器并在 Ubuntu(虚拟机)上运行测试。

警告

  • -printf选项在 Ubuntu 上运行良好,但不适用于 MacOS。
于 2018-11-24T18:28:22.880 回答