Постоянно проверяйте, изменен ли файл bash

8

У меня есть файл с именем file1, который я хочу в скрипте, всякий раз, когда в нем есть изменения, делайте что-то, фактически звуковой сигнал. Как я могу это сделать?

Адон
источник

Ответы:

14

Если вы inotify-toolsустановили (по крайней мере, это имя пакета в Debian), когда вы можете сделать что-то вроде этого:

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

Это ожидает события «modify» с файлом с именем «filename». Когда это происходит, inotifywaitкоманда выводит filename MODIFY(которую мы отбрасываем, отправляя вывод в / dev / null), а затем завершается, что приводит к вводу тела цикла.

Прочтите справочную страницу для inotifywaitполучения дополнительных возможностей.

wurtel
источник
Хороший вопрос, я не очень хорошо прочитал man-
страницу
Вам не нужно строго while. Также обратите внимание, что то, что человек считает «модифицировать», может не всегда работать: например, он будет ловить добавление, но не будет отлавливать редактор, такой как vim(просматриваемый файл переименовывается или заменяется резервной копией) или perl -i(на месте) редактировать), который заменяет файл новым. Как только это произойдет, inotifywaitникогда не вернется. Просмотр inode и просмотр имени файла - это не одно и то же, поэтому это зависит от варианта использования.
mr.spuratic
1
Вы можете добавить другие события для ожидания, например move_self, перехватывать переименования. Смотрите man-страницу для полного списка событий.
wurtel
2

Без inotifywait вы можете использовать этот маленький скрипт и задание cron (каждую минуту или около того):

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

Пришел искать однострочник на MacOS. Поселился на следующем. Скомпилировал и добавил этот инструмент в мой путь. Это заняло менее 30 секунд.

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

Затем я пошел в каталог, в котором я хотел сделать просмотр. В этом случае я хотел посмотреть файл уценки на наличие изменений, и если он был изменен, выдайте сообщение a make.

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

Вот и все.

Джошуа Кук
источник
1
как заметка, работало хорошо (если содержимое файла меняется), кажется, что это только OS X, и вы можете установить представление, brew install kqwaitи вы можете передать несколько файлов ему, какkqwait **/*
rogerdpack
0

Вам, вероятно, не нужно сравнивать md5sum, если у вас есть доступная утилита 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

! отрицает, например, истина, если утверждение ложно

Предостережение: вам нужен исходный файл для сравнения с diff, который (imo) совпадает с тем, что делает скрипт md5sum выше.

Jetchisel
источник
Используйте diff -q, если diffподдерживает это.
Муру
Хорошо, давайте попробуем это: echo foo> foo.txt; эхо-бар> bar.txt; diff foo.txt bar.txt -> Файлы foo и bar отличаются ## (так много, что вполне :))
Jetchisel
1
Это тише, чем прописывать все различия. -qозначает «отчет, если только файлы отличаются», а не как они отличаются. Таким образом, diff -qпрекращается сравнение в тот момент, когда видна разница, что может быть очень полезным с точки зрения производительности. См. Документацию GNU , например. Если весь смысл вашего ответа эффективен, если не использовать md5sum, то отказ от использования, diff -qесли он доступен, побеждает этот пункт.
Муру
Хорошо, -q "мудрость производительности" это хорошо, но она все равно что-то печатает в stdout / stderr, если файл отличается друг от друга. Я изложил! который отрицал не я? то, что мне нужно, это состояние выхода diff, отличное от 0 (см. документацию GNU), затем принять меры.
Jetchisel
Вы упускаете суть. У меня больше нет желания объяснять.
Муру
0

Вы можете попробовать entrинструмент командной строки, например,

$ ls file1 | entr beep
kenorb
источник
entrдолжен быть установлен или, по крайней мере, так обстоит дело с Ubuntu. Он должен присутствовать в большинстве дистрибутивных репозиториев.
rbaleksandar
0

если вы проверяете изменения в git-репо, вы можете использовать:

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

а. cp orginalfile fileneedto_be_changed'(Нужно сделать только один раз)

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

б.

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
Правин Кумар Б.С.
источник