Controlla costantemente se il file viene modificato bash


8

Ho un file chiamato file1 che voglio in uno script, ogni volta che c'è un cambiamento in esso, fare qualcosa, in realtà emette un segnale acustico. Come lo faccio?

Risposte:


14

Se hai inotify-toolsinstallato (almeno quello è il nome del pacchetto su Debian) quando puoi fare qualcosa del genere:

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

Ciò attende che l'evento "modifica" si verifichi nel file denominato "nome file". Quando ciò accade, il inotifywaitcomando genera filename MODIFY(che scartiamo inviando l'output a / dev / null) e quindi termina, causando l'immissione del corpo del loop.

Leggi la manpage inotifywaitper maggiori possibilità.


Bene, non avevo letto bene la manpage :-)
wurtel

Non è strettamente necessario while. Si noti inoltre che ciò che un essere umano considera una "modifica" potrebbe non funzionare sempre: questo prenderà ad esempio un'appendice, ma non catturerà un editor come vim(il file guardato viene rinominato o scambiato con un backup), né perl -i(sul posto modifica) che sostituisce il file con uno nuovo. Una volta che uno di questi accade, inotifywaitnon tornerà mai più. Guardare un inode e guardare un nome di file non è la stessa cosa, quindi dipende dal caso d'uso.
mr.spuratic

1
È possibile aggiungere altri eventi da attendere, ad es move_self. Acquisirà i nomi. Vedi la manpage per l'elenco completo degli eventi.
wurtel

2

Senza inotifywait puoi usare questo piccolo script e un cron job (ogni minuto circa):

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

È venuto alla ricerca di un one-liner su MacOS. Stabilito quanto segue. Compilato e aggiunto questo strumento al mio percorso. Ci sono voluti meno di 30 secondi.

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

Successivamente, sono andato alla directory in cui desideravo fare la visione. In questo caso, volevo guardare un file markdown per le modifiche e, se modificato, a make.

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

Questo è tutto.


1
come nota, ha funzionato bene (se il contenuto del file cambia), sembra essere solo OS X e puoi installare la vista brew install kqwaite puoi passarci più file comekqwait **/*
rogerdpack

0

Probabilmente non avrai bisogno di confrontare md5sum se hai l'utilità diff disponibile.

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

il ! nega es. vero se l'affermazione è falsa

Un avvertimento è che hai bisogno del file originale per confrontare con diff quale (imo) lo stesso di quello che sta facendo lo script md5sum sopra.


Usa diff -q, se lo diffsupporta.
Muru,

Ok proviamo quello: echo foo> foo.txt; echo bar> bar.txt; diff foo.txt bar.txt -> I file foo e bar differiscono ## (tanto per essere abbastanza :))
Jetchisel

1
È più silenzioso di ogni spiegazione spiegata. -qsignifica "segnala se solo i file differiscono", non come differiscono. Quindi diff -qsmette di confrontare il momento in cui si vede una differenza, che può essere molto utile dal punto di vista delle prestazioni. Vedi la documentazione GNU , per esempio. Se l'intero punto della tua risposta è efficiente non usando md5sum, allora non usare diff -qse disponibile significa sconfiggere quel punto.
Muru,

Ok, -q "per quanto riguarda le prestazioni" va bene, ma stampa comunque qualcosa su stdout / stderr se il file differisce l'uno dall'altro. Ho dichiarato il! quale negazione no? quello che sto cercando dopo è che lo stato di uscita di diff non è 0, (Vedi la documentazione GNU) quindi agire.
Jetchisel,

Ti manca il punto. Non ho più voglia di spiegare.
Muru,

0

Puoi provare lo entrstrumento da riga di comando, ad es

$ ls file1 | entr beep

entrdeve essere installato o almeno questo è il caso di Ubuntu. Dovrebbe essere presente nella maggior parte dei repository distorti là fuori però.
rbaleksandar,

0

se stai verificando le modifiche in un repository git, puoi usare:

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

un. cp orginalfile fileneedto_be_changed'(Bisogna fare solo una volta)

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

b.

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.