Linux 如何在文件或目录更改时运行 shell 脚本?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4060212/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to run a shell script when a file or directory changes?
提问by Drew LeSueur
I want to run a shell script when a specific file or directory changes.
我想在特定文件或目录更改时运行 shell 脚本。
How can I easily do that?
我怎样才能轻松做到这一点?
采纳答案by Frédéric Hamidi
Use inotify-tools.
回答by Brian Clements
Check out the kernel filesystem monitor daemon
查看内核文件系统监视器守护进程
http://freshmeat.net/projects/kfsmd/
http://freshmeat.net/projects/kfsmd/
Here's a how-to:
这是一个操作方法:
回答by Yoric
回答by slowdog
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”,它“监视目录并存档任何新的或更改的文件”。
回答by VDR
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
回答by Dominykas Mostauskis
I use this script to run a build script on changes in a directory tree:
我使用此脚本在目录树中的更改上运行构建脚本:
#!/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
Uses inotify-tools
. Check inotifywait
man pagefor how to customize what triggers the build.
使用inotify-tools
. 查看inotifywait
手册页了解如何自定义触发构建的内容。
回答by jonatan
Just for debugging purposes, when I write a shell script and want it to run on save, I use this:
只是为了调试目的,当我编写一个 shell 脚本并希望它在保存时运行时,我使用这个:
#!/bin/bash
file="" # Name of file
command="${*:2}" # Command to run on change (takes rest of line)
t1="$(ls --full-time $file | awk '{ print }')" # Get latest save time
while true
do
t2="$(ls --full-time $file | awk '{ print }')" # 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 }')"
回答by Dan Garthwaite
Add the following to ~/.bashrc:
将以下内容添加到 ~/.bashrc:
function react() {
if [ -z "" -o -z "" ]; then
echo "Usage: react <[./]file-to-watch> <[./]action> <to> <take>"
elif ! [ -r "" ]; then
echo "Can't react to , permission denied"
else
TARGET=""; shift
ACTION="$@"
while sleep 1; do
ATIME=$(stat -c %Z "$TARGET")
if [[ "$ATIME" != "${LTIME:-}" ]]; then
LTIME=$ATIME
$ACTION
fi
done
fi
}
回答by kenorb
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
or print Changed!
when file file.txt
is saved:
或Changed!
在file.txt
保存文件时打印:
$ echo file.txt | entr echo Changed!
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
回答by Is Ma
Suppose you want to run rake test
every time you modify any ruby file ("*.rb") in app/and test/directories.
假设您想在rake test
每次修改app/和test/目录中的任何 ruby 文件(“*.rb”)时运行。
Just get the most recent modified time of the watched files and check every second if that time has changed.
只需获取所监视文件的最新修改时间,并每秒检查该时间是否已更改。
Script code
脚本代码
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
Benefits
好处
- You can run any command or script when the file changes.
- It works between any filesystem and virtual machines (shared folders on VirtualBox using Vagrant); so you can use a text editor on your Macbook and run the tests on Ubuntu (virtual box), for example.
- 当文件更改时,您可以运行任何命令或脚本。
- 它适用于任何文件系统和虚拟机(VirtualBox 上使用 Vagrant 的共享文件夹);例如,您可以在 Macbook 上使用文本编辑器并在 Ubuntu(虚拟机)上运行测试。
Warning
警告
- The
-printf
option works well on Ubuntu, but do not work in MacOS.
- 该
-printf
选项在 Ubuntu 上运行良好,但在 MacOS 中不起作用。