
Ich versuche, ein Skript zu erstellen, das erkennt, ob eine der Dateien in einem Verzeichnis innerhalb eines 2-Sekunden-Intervalls geändert wurde. Bisher habe ich Folgendes:
#!/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
Dies gibt nur einmal den Wert „Identisch“ aus, ich möchte, dass es jede Datei prüft und für jede Datei „Identisch“ oder „Unterschiedlich“ ausgibt.
Bearbeiten: Kann dies ohne die Installation derinotify-tools
Paket?
Antwort1
Sie könneninotify-toolsauf jeden Fall von der Kommandozeile aus, zB so:
inotifywait -r -m /dir/to/monitor/
-m
,--monitor
Anstatt nach dem Empfang eines einzelnen Ereignisses zu beenden, führen Sie es auf unbestimmte Zeit aus. Das Standardverhalten besteht darin, nach dem Auftreten des ersten Ereignisses zu beenden.
Und hier ist ein Skript, das kontinuierlich überwacht, kopiert aus der Man-Datei von 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
Antwort2
Wie andere bereits erklärt haben, inotify
ist die Verwendung die bessere Lösung. Ich erkläre nur, warum Ihr Skript fehlschlägt. Zunächst einmal gilt: Egal, in welcher Sprache Sie programmieren, wenn Sie versuchen, etwas zu debuggen, lautet die erste Regel „alle Variablen drucken“:
$ ls
file1 file2 file3
$ echo $PWD
/home/terdon/foo
$ for FILE in "${PWD}/*"; do echo "$FILE"; done
/home/terdon/foo/*
Wie Sie oben sehen können, $FILE
wird tatsächlich erweitert auf $PWD/*
. Daher wird die Schleife nur einmal auf derSchnur /home/terdon/foo/*
und nicht auf jede einzelne Datei im Verzeichnis einzeln. Dann md5sum
lautet der Befehl:
md5sum /home/terdon/foo/*
Mit anderen Worten, es wird md5sum
auf allen Dateien im Zielverzeichnis gleichzeitig ausgeführt und nicht auf jeder einzelnen.
Das Problem besteht darin, dass Sie Ihre Glob-Erweiterung zitieren und dies verhindert, dass sie erweitert wird:
$ echo "*"
*
$ echo *
file1 file2 file3
WährendVariablensollte fastimmer zitiert werden, Globs sollten dies nicht tun, da sie dadurch zu Strings statt zu Globs werden.
Sie wollten Folgendes tun:
for FILE in "${PWD}"/*; do ...
Es gibt jedoch keinen Grund, es $PWD
hier zu verwenden, da es nichts Nützliches hinzufügt. Die obige Zeile entspricht:
for FILE in *; do
Vermeiden Sie außerdem die Verwendung von GROSSBUCHSTABEN für Shellvariablen. Diese werden für die vom System festgelegten Umgebungsvariablen verwendet und es ist besser, Ihre eigenen Variablen in Kleinbuchstaben zu schreiben.
Vor diesem Hintergrund finden Sie hier eine funktionierende, verbesserte Version Ihres Skripts:
#!/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
Antwort3
Mit dem Paket können Sie inotify-tools
alle Änderungen in einem Ordner in Echtzeit überwachen. Es enthält beispielsweise das inotifywait
Tool, das Sie wie folgt verwenden können:
> inotifywait /tmp
Setting up watches.
Watches established.
/tmp/ MODIFY test
Sie können Flags verwenden, um nur bestimmte Ereignisse oder bestimmte Dateien zu filtern. Das inotifywatch
Tool sammelt Statistiken zur Dateisystemnutzung und gibt die Anzahl der einzelnen inotify
Ereignisse aus.
Wenn Sie mit anderen Tools überwachen möchten, können Sie find
den -mmin
Parameter (modifizierte Minuten) verwenden. Da 2 Sekunden 0,033 Minuten entsprechen, könnten Sie Folgendes verwenden:
find . -type f -mmin 0.033
Antwort4
#!/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