当文件或目录发生变化时,如何运行 shell 脚本?
- 2024-10-14 08:40:00
- admin 原创
- 73
问题描述:
我想在特定文件或目录发生变化时运行 shell 脚本。
我怎样才能轻松地做到这一点?
解决方案 1:
您可以尝试使用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
解决方案 2:
我使用这个脚本来对目录树中的更改运行构建脚本:
#!/bin/bash -eu
DIRECTORY_TO_OBSERVE="js" # might want to change this
function block_for_change {
inotifywait --recursive \n --event modify,move,create,delete \n $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
手册页以了解如何自定义触发构建的操作。
解决方案 3:
使用inotify-tools。
链接的 Github 页面有许多示例;这里是其中之一。
#!/bin/sh
cwd=$(pwd)
inotifywait -mr \n --timefmt '%d/%m/%y %H:%M' --format '%T %w %f' \n -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" \n usernam@example.com:/backup/root/dir && \n echo "At ${time} on ${date}, file $changed_abs was backed up via rsync" >&2
done
解决方案 4:
这个脚本怎么样?使用“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
解决方案 5:
检查内核文件系统监视守护进程
http://freshmeat.net/projects/kfsmd/
以下是操作方法:
http://www.linux.com/archive/feature/124903
解决方案 6:
如上所述,inotify-tools 可能是最好的选择。但是,如果您编程只是为了好玩,您可以尝试明智地使用tail -f来获得黑客 XP 。
解决方案 7:
仅出于调试目的,当我编写 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 }')"
解决方案 8:
将以下内容添加到〜/.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
}
解决方案 9:
对于想要跟踪单个文件的 fish shell 用户的快速解决方案:
while true
set old_hash $hash
set hash (md5sum file_to_watch)
if [ $hash != $old_hash ]
command_to_execute
end
sleep 1
end
md5sum
在 macos 上用if替换md5
。
解决方案 10:
这是另一个选择:http://fileschanged.sourceforge.net/
尤其请参阅“示例 4”,其中“监视目录并存档任何新的或更改的文件”。
解决方案 11:
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
解决方案 12:
假设您想要在rake test
每次修改app/和test/目录中的任何 ruby 文件(“* .rb”)时运行。
只需获取所监视文件的最近修改时间并每秒检查一次该时间是否发生变化。
脚本代码
t_ref=0; while true; do t_curr=$(find app/ test/ -type f -name "*.rb" -printf "%T+
" | sort -r | head -n1); if [ $t_ref != $t_curr ]; then t_ref=$t_curr; rake test; fi; sleep 1; done
好处
当文件发生变化时,您可以运行任何命令或脚本。
它可以在任意文件系统和虚拟机(使用 Vagrant 在 VirtualBox 上共享文件夹)之间工作;因此,您可以在 Macbook 上使用文本编辑器并在 Ubuntu(虚拟盒)上运行测试。
警告
该
-printf
选项在 Ubuntu 上运行良好,但在 MacOS 上不起作用。
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件