
Я пытаюсь сделать скрипт, который определяет, были ли изменены какие-либо файлы в каталоге в течение 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
Покапеременныедолжен почтивсегда цитироваться, глобусы не должны этого делать, поскольку это превращает их в строки, а не в глобусы.
Вы имели в виду следующее:
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