Verifique constantemente se o arquivo é modificado


8

Eu tenho um arquivo chamado file1 que eu quero em um script, sempre que houver uma alteração nele, faça alguma coisa, um bipe soará. Como faço isso?

Respostas:


14

Se você inotify-toolsinstalou (pelo menos esse é o nome do pacote no Debian) quando você pode fazer algo assim:

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

Isso aguarda o evento "modify" acontecer com o arquivo chamado "filename". Quando isso acontece, o inotifywaitcomando sai filename MODIFY(que descartamos enviando a saída para / dev / null) e depois termina, o que faz com que o corpo do loop seja inserido.

Leia a página de manual inotifywaitpara mais possibilidades.


Bom ponto, eu não tinha lido a página de manual que bem :-)
wurtel

Você não precisa estritamente while. Observe também que o que um humano considera uma "modificação" nem sempre funciona: isso trará um acréscimo, por exemplo, mas não capturará um editor como vim(o arquivo assistido é renomeado ou trocado por um backup), nem perl -i(in-loco editar) que substitui o arquivo por um novo. Uma vez que um desses aconteça, inotifywaitnunca mais retornará. Assistir a um inode e assistir a um nome de arquivo não é a mesma coisa, portanto, depende do caso de uso.
precisa saber é o seguinte

1
Você pode adicionar outros eventos para aguardar, por exemplo move_self, pegará renomeados. Veja a página de manual para obter uma lista completa dos eventos.
wurtel

2

Sem inotifywait, você pode usar este pequeno script e um trabalho cron (a cada minuto ou mais):

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

Veio à procura de uma linha no MacOS. Resolvido no seguinte. Compilei e adicionei essa ferramenta ao meu caminho. Isso levou menos de 30 segundos.

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

Em seguida, fui ao diretório em que desejava assistir. Nesse caso, eu gostaria de assistir a um arquivo de remarcação para alterações e, se alterado, a make.

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

É isso aí.


1
como uma nota, funcionou bem (se o conteúdo do arquivo mudar), parece ser apenas OS X, e você pode instalar vista brew install kqwaite você pode passar vários arquivos a ele comokqwait **/*
rogerdpack

0

Você provavelmente não precisa comparar o md5sum se tiver o utilitário diff disponível.

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

a ! nega, por exemplo, true se a declaração for falsa

Advertência é que você precisa do arquivo original para comparar com o diff, que (imo) é o mesmo que o script md5sum está fazendo acima.


Use diff -q, se for diffcompatível.
Muru

Ok, vamos tentar o seguinte: echo foo> foo.txt; barra de eco> bar.txt; diff bar.txt foo.txt -> arquivos foo e bar diferem ## (tanto para estar bastante :))
Jetchisel

1
É mais silencioso do que ter todas as diferenças explicitadas. -qsignifica "relatar se apenas os arquivos diferem", não como eles diferem. Portanto, diff -qpara de comparar o momento em que uma diferença é vista, o que pode ser muito útil em termos de desempenho. Veja a documentação do GNU , por exemplo. Se todo o ponto de sua resposta estiver sendo eficiente por não usar md5sum, o não uso, diff -qse disponível, está derrotando esse ponto.
Muru

Ok, -q "performance wise" que é bom, mas ainda imprime algo em stdout / stderr se o arquivo diferir um do outro. Eu declarei o! qual negar não foi? o que estou procurando é que o status de saída do diff não seja 0, (consulte a documentação do GNU) e tome uma atitude.
Jetchisel

Você está perdendo o ponto. Não tenho mais desejo de explicar.
Muru

0

Você pode experimentar entra ferramenta de linha de comando, por exemplo

$ ls file1 | entr beep

entrprecisa ser instalado ou, pelo menos, é o caso do Ubuntu. Ele deve estar presente na maioria dos repositórios de distorções existentes no mercado.
rbaleksandar

0

se você estiver verificando alterações em um repositório git, poderá 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

uma. cp orginalfile fileneedto_be_changed'(Precisa fazer apenas uma vez)

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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.