Bash 脚本检测目录中文件的更改

Bash 脚本检测目录中文件的更改

我正在尝试制作一个脚本来检测目录中的任何文件是否在 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/

人 inotify 等待

-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

相关内容