我希望在特定文件或目录更改时运行shell脚本。
我怎样才能轻松做到?
答案 0 :(得分:24)
我使用此脚本在目录树中的更改上运行构建脚本:
#!/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,了解如何自定义触发构建的内容。
答案 1 :(得分:21)
答案 2 :(得分:14)
您可以尝试使用entr
工具在文件更改时运行任意命令。文件示例:
$ 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
答案 3 :(得分:3)
答案 4 :(得分:2)
如上所述,inotify-tools可能是最好的主意。但是,如果您正在编程以获得乐趣,则可以通过明智地应用tail -f来尝试获取黑客XP。
答案 5 :(得分:1)
这是另一种选择:http://fileschanged.sourceforge.net/
特别参见“示例4”,它“监视目录并存档任何新的或更改的文件”。
答案 6 :(得分:1)
这个脚本怎么样?使用'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
答案 7 :(得分: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
答案 8 :(得分: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 }')"
答案 9 :(得分: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
}
答案 10 :(得分: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"