我正在尝试制作一个脚本来检测目录中的任何文件是否在 2 秒间隔内发生更改。到目前为止我所拥有的是:
#!/bin/bash
for FILE in "${PWD}/*"
do
SUM1="$(md5sum $FILE)"
sleep 2
SUM2="$(md5sum $FILE)"
if [ "$SUM1" = "$SUM2" ];
then
echo "Identical"
else
echo "Different"
fi
done
这仅输出一次值“相同”,我希望它检查每个文件并为每个文件输出“相同”或“不同”。
编辑: 不安装的话可以吗inotify-tools
包裹?
答案1
您可以使用inotify 工具绝对是从命令行,例如这样:
inotifywait -r -m /dir/to/monitor/
-m
,--monitor
不是在收到单个事件后退出,而是无限期地执行。默认行为是在第一个事件发生后退出。
这是一个连续监控的脚本,从 man 文件复制inotifywait
:
#!/bin/sh
while inotifywait -e modify /var/log/messages; do
if tail -n1 /var/log/messages | grep apache; then
kdialog --msgbox "Blah blah Apache"
fi
done
答案2
正如其他人所解释的,使用inotify
是更好的解决方案。我将解释为什么你的脚本失败。首先,无论您使用哪种语言进行编程,每当您尝试调试某些内容时,第一条规则都是“打印所有变量”:
$ ls
file1 file2 file3
$ echo $PWD
/home/terdon/foo
$ for FILE in "${PWD}/*"; do echo "$FILE"; done
/home/terdon/foo/*
因此,正如您在上面看到的,$FILE
实际上扩展为$PWD/*
.因此,循环只运行一次细绳 /home/terdon/foo/*
而不是分别针对目录中的每个文件。那么,md5sum
命令就变成:
md5sum /home/terdon/foo/*
换句话说,它会md5sum
同时在目标目录中的所有文件上运行,而不是在每个文件上运行。
问题是您正在引用您的全局扩展,这会阻止它扩展:
$ echo "*"
*
$ echo *
file1 file2 file3
尽管变量应该差不多总是被引用,glob 不应该这样,因为这会使它们变成字符串而不是 glob。
你想做的是:
for FILE in "${PWD}"/*; do ...
然而,没有理由$PWD
在这里使用,它没有添加任何有用的东西。上面的行相当于:
for FILE in *; do
另外,避免对 shell 变量使用大写字母。这些用于系统设置的环境变量,最好将您自己的变量保留为小写。
考虑到所有这些,这是脚本的一个有效的改进版本:
#!/bin/bash
for file in *
do
sum1="$(md5sum "$file")"
sleep 2
sum2="$(md5sum "$file")"
if [ "$sum1" = "$sum2" ];
then
echo "Identical"
else
echo "Different"
fi
done
答案3
您可以使用该inotify-tools
包实时监控文件夹中的所有更改。例如,它包含inotifywait
您可以使用的工具,例如:
> inotifywait /tmp
Setting up watches.
Watches established.
/tmp/ MODIFY test
您可以使用标志仅过滤某些事件或某些文件。该inotifywatch
工具收集文件系统使用情况统计信息并输出每个inotify
事件的计数。
如果想用其他工具监控,可以find
配合-mmin
参数(修改分钟)使用。由于 2 秒相当于 0.033 分钟,因此您可以使用:
find . -type f -mmin 0.033
答案4
#!/bin/bash
# pass one or more folders as arguments
while true; do
for f in "$@"; do
date
echo "Checking $f and subfolders"
find=$(find "$f" -type f)
while read -r f2; do
# strip non-alphanumeric from filename for a variable var name
v=${f2//[^[:alnum:]]/}
r=$(md5sum "$f2")
if [ "$r" = "${!v}" ]; then
echo "Identical $f2"
else
echo "Different $f2"
fi
eval "${v}=\$r"
done <<< "$find"
done
sleep 2
done