
Estoy intentando crear un script que detecte si alguno de los archivos de un directorio se modificó en un intervalo de 2 segundos. Lo que tengo hasta ahora es:
#!/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
Esto genera solo una vez el valor "Idéntico", quiero que verifique cada archivo y genere "Idéntico" o "Diferente" para cada archivo.
Editar: ¿Se puede hacer esto sin instalar elinotify-tools
¿paquete?
Respuesta1
Puedes usarherramientas-inotifydefinitivamente desde la línea de comando, por ejemplo, así:
inotifywait -r -m /dir/to/monitor/
-m
,--monitor
En lugar de salir después de recibir un solo evento, ejecútelo indefinidamente. El comportamiento predeterminado es salir después de que ocurra el primer evento.
Y aquí hay un script que monitorea continuamente, copiado del archivo man de 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
Respuesta2
Como otros han explicado, usar inotify
es la mejor solución. Simplemente explicaré por qué falla tu script. En primer lugar, no importa en qué lenguaje estés programando, cada vez que intentas depurar algo, la primera regla es "imprimir todas las variables":
$ ls
file1 file2 file3
$ echo $PWD
/home/terdon/foo
$ for FILE in "${PWD}/*"; do echo "$FILE"; done
/home/terdon/foo/*
Entonces, como puede ver arriba, $FILE
en realidad se expande a $PWD/*
. Por lo tanto, el bucle sólo se ejecuta una vez en elcadena /home/terdon/foo/*
y no en cada uno de los archivos del directorio individualmente. Entonces, el md5sum
comando se convierte en:
md5sum /home/terdon/foo/*
En otras palabras, se ejecuta md5sum
en todos los archivos del directorio de destino a la vez y no en cada uno de ellos.
El problema es que estás citando tu expansión global y eso impide que se expanda:
$ echo "*"
*
$ echo *
file1 file2 file3
Mientrasvariablesdebería casisiempre ser citado, los globos no deberían hacerlo, ya que eso los convierte en cadenas en lugar de globos.
Lo que querías hacer es:
for FILE in "${PWD}"/*; do ...
Sin embargo, no hay ninguna razón para usarlo $PWD
aquí, no agrega nada útil. La línea de arriba es equivalente a:
for FILE in *; do
Además, evite el uso de letras MAYÚSCULAS para las variables del shell. Se utilizan para las variables ambientales establecidas por el sistema y es mejor mantener sus propias variables en minúsculas.
Con todo esto en mente, aquí tienes una versión funcional y mejorada de tu script:
#!/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
Respuesta3
Puede utilizar el inotify-tools
paquete para monitorear todos los cambios en una carpeta en tiempo real. Por ejemplo, contiene la inotifywait
herramienta que podría utilizar como:
> inotifywait /tmp
Setting up watches.
Watches established.
/tmp/ MODIFY test
Puede utilizar indicadores para filtrar solo ciertos eventos o ciertos archivos. La inotifywatch
herramienta recopila estadísticas de uso del sistema de archivos y genera recuentos de cada inotify
evento.
Si desea monitorear con otras herramientas, puede usar find
el -mmin
parámetro (minutos modificados). Dado que 2 segundos son como 0,033 minutos, podrías usar:
find . -type f -mmin 0.033
Respuesta4
#!/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