Compruebe constantemente si el archivo se modifica bash


8

Tengo un archivo llamado file1 que quiero en un script, cada vez que hay un cambio en él, hago algo, un pitido en realidad. ¿Cómo puedo hacer eso?

Respuestas:


14

Si ha inotify-toolsinstalado (al menos ese es el nombre del paquete en Debian) cuando puede hacer algo como esto:

while inotifywait -q -e modify filename >/dev/null; do
    echo "filename is changed"
    # do whatever else you need to do
done

Esto espera a que ocurra el evento "modificar" en el archivo llamado "nombre de archivo". Cuando eso sucede, el inotifywaitcomando emite filename MODIFY(que descartamos enviando la salida a / dev / null) y luego termina, lo que hace que se ingrese el cuerpo del bucle.

Lea la página de manual inotifywaitpara más posibilidades.


Buen punto, no había leído bien la página de
manual

No es estrictamente necesario while. También tenga en cuenta que lo que un humano considera una "modificación" no siempre funciona: esto capturará un apéndice, por ejemplo, pero no detectará un editor como vim(el archivo observado se renombra o se intercambia con una copia de seguridad), ni perl -i(en el lugar editar) que reemplaza el archivo con uno nuevo. Una vez que cualquiera de esos ocurra, inotifywaitnunca volverá. Mirar un inodo y mirar un nombre de archivo no es lo mismo, por lo que depende del caso de uso.
Sr.Spuratic

1
Puede agregar otros eventos para esperar, por ejemplo move_self, capturará los cambios de nombre. Consulte la página de manual para obtener una lista completa de eventos.
wurtel

2

Sin inotifywait puedes usar este pequeño script y un trabajo cron (cada minuto más o menos):

#!/usr/bin/env bash
#
# Provides      : Check if a file is changed
# 
# Limitations   : none
# Options       : none
# Requirements  : bash, md5sum, cut
# 
# Modified      : 11|07|2014
# Author        : ItsMe
# Reply to      : n/a in public
#
# Editor        : joe
#
#####################################
#
# OK - lets work
#

# what file do we want to monitor?
# I did not include commandline options
# but its easy to catch a command line option
# and replace the defaul given here
file=/foo/bar/nattebums/bla.txt

# path to file's saved md5sum
# I did not spend much effort in naming this file
# if you ahve to test multiple files
# so just use a commandline option and use the given
# file name like: filename=$(basename "$file")
fingerprintfile=/tmp/.bla.md5savefile

# does the file exist?
if [ ! -f $file ]
    then
        echo "ERROR: $file does not exist - aborting"
    exit 1
fi

# create the md5sum from the file to check
filemd5=`md5sum $file | cut -d " " -f1`

# check the md5 and
# show an error when we check an empty file
if [ -z $filemd5 ]
    then
        echo "The file is empty - aborting"
        exit 1
    else
        # pass silent
        :
fi

# do we have allready an saved fingerprint of this file?
if [ -f $fingerprintfile ]
    then
        # yup - get the saved md5
        savedmd5=`cat $fingerprintfile`

        # check again if its empty
        if [ -z $savedmd5 ]
            then
                echo "The file is empty - aborting"
                exit 1
        fi

        #compare the saved md5 with the one we have now
        if [ "$savedmd5" = "$filemd5" ]
            then
                # pass silent
                :
            else
                echo "File has been changed"

                # this does an beep on your pc speaker (probably)
                # you get this character when you do:
                # CTRL+V CTRL+G
                # this is a bit creepy so you can use the 'beep' command
                # of your distro
                # or run some command you want to
                echo 
        fi

fi

# save the current md5
# sure you don't have to do this when the file hasn't changed
# but you know I'm lazy and it works...
echo $filemd5 > $fingerprintfile

2

Vino a buscar un one-liner en MacOS. Establecido en lo siguiente. Compilado y agregado esta herramienta a mi camino. Esto tomó menos de 30 segundos.

$ git clone git@github.com:sschober/kqwait.git
$ cd kqwait
$ make
$ mv kqwait ~/bin
$ chmod +x ~/bin/kqwait

Luego, fui al directorio en el que deseaba hacer la observación. En este caso, deseaba ver un archivo de rebajas para ver los cambios, y si se modifica, emitir un make.

$ while true; do kqwait doc/my_file.md; make; done

Eso es.


1
como nota, funcionó bien (si el contenido del archivo cambia), parece ser solo OS X, y puede instalar view brew install kqwaity puede pasarle múltiples archivos comokqwait **/*
rogerdpack

0

Probablemente no necesite comparar md5sum si tiene disponible la utilidad diff.

if ! diff "$file1" "$file2" >/dev/null 2>&1; then
  echo "$file1 and $file2 does not match" >&2
  ## INSERT-YOUR-COMMAND/SCRIPT-HERE
  ## e.g. cp "$file1" "$file2"
fi

la ! niega, por ejemplo, verdadero si la declaración es falsa

La advertencia es que necesita el archivo original para comparar con diff que (imo) es lo mismo que el script md5sum está haciendo anteriormente.


Uso diff -q, si lo diffsoporta.
muru

Ok, intentemos eso: echo foo> foo.txt; echo bar> bar.txt; diff foo.txt bar.txt -> Los archivos foo y bar difieren ## (tanto por ser bastante :))
Jetchisel

1
Es más silencioso que tener cada diferencia enunciada. -qsignifica "informar si solo difieren los archivos", no cómo difieren. Entonces diff -qdeja de comparar el momento en que se ve una diferencia, lo que puede ser muy útil en cuanto al rendimiento. Consulte la documentación de GNU , por ejemplo. Si el punto completo de su respuesta es ser eficiente al no usarlo md5sum, entonces no usarlo diff -qsi está disponible es derrotar ese punto.
muru

Ok, -q "en cuanto al rendimiento" es bueno, pero aún imprime algo en stdout / stderr si el archivo difiere entre sí. Dije el! ¿Qué negado no? lo que busco es que el estado de salida de diff no sea 0 (consulte la documentación de GNU) y luego tome medidas.
Jetchisel

Te estás perdiendo el punto. No tengo más ganas de explicarlo.
muru

0

Puede probar la entrherramienta de línea de comandos, p. Ej.

$ ls file1 | entr beep

entrnecesita ser instalado o al menos ese es el caso de Ubuntu. Sin embargo, debería estar presente en la mayoría de los repositorios de distorsión.
rbaleksandar

0

si está verificando cambios en un repositorio de git, puede usar:

#!/usr/bin/env bash

diff="$(git diff | egrep some_file_name_or_file_path | cat)"

if [[ -n "$diff" ]] ; then
    echo "==== Found changes: ===="
    echo "diff: $diff"
    exit 1
else
    echo 'Code is not changed'
fi

0
Done in 2 steps Tested and worked fine in both scenarios

a. cp orginalfile fileneedto_be_changed'(Necesito hacer solo una vez)

orginalfile=====>which supposed to be changed

si.

differencecount=`awk 'NR==FNR{a[$0];next}!($0 in a){print $0}' orginalfile fileneedto_be_changed|wc -l`

if [ $differencecount -eq  0 ]
then
echo "NO changes in file"
else
echo "Noted there is changes in file"
fi
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.