Скрипт 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/

Отчеловек inotifywait

-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

Покапеременныедолжен почтивсегда цитироваться, глобусы не должны этого делать, поскольку это превращает их в строки, а не в глобусы.

Вы имели в виду следующее:

for FILE in "${PWD}"/*; do ...

Однако нет смысла использовать $PWDздесь, это не добавляет ничего полезного. Строка выше эквивалентна:

for FILE in *; do

Также избегайте использования ЗАГЛАВНЫХ букв для переменных оболочки. Они используются для системных переменных окружения, и лучше хранить собственные переменные в нижнем регистре.

Учитывая все это, вот рабочая, улучшенная версия вашего скрипта:

#!/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

Связанный контент