Обновить контрольную сумму md5 при изменении файлов

У меня есть сервер, который при изменении содержимого конкретной папки вычисляет контрольную сумму.

Проблема в том, что вычисление контрольной суммы занимает около 30 минут с момента пересчета каждого отдельного файла в этой папке, даже если был изменен простой текстовый файл. Таким образом, пока контрольная сумма работает, файлы не должны использоваться.

Расчет контрольной суммы выполняется с помощью следующей команды:

find . -type f | xargs md5sum > some_file

Каждый день новые файлы добавляются в папку, а другие удаляются.

Есть ли способ обновить файл контрольной суммы только на измененных / добавленных / удаленных файлах без вычисления md5 для остальных файлов?

Изменить: Уточнение

Контрольная сумма должна содержать md5 для каждого отдельного файла в этой папке. То, что я пытаюсь достичь, - это способ редактировать / обновлять файл контрольной суммы, когда что-то меняется в папке:

Удалить md5 для файла при удалении Добавить md5 для файла при добавлении в папку Обновить хеш-код, когда файл измененный

Все это без пересчета всей папки сверху

0
задан 29 December 2017 в 14:40

3 ответа

Это очень грубый сценарий, который пытается сделать то, что вы хотите. Не стесняйтесь копировать, изменять, оптимизировать - было бы неплохо иметь некоторый отклик, если он сработает для вас. Если они были протестированы в моей папке «Загрузки» и обнаружили только одну ошибку слева (имя файла, содержащее [, которое не понравилось grep).

Изменить: Изменен источник снова, поскольку создание временные метки (в первой версии) больше не нужны, поскольку новые / измененные файлы найдены с помощью find -newer. Также добавлены параметры для определения имени хэш-файла и, возможно, верхней папки для начала; поэтому сценарий не нужно вызывать из верхнего каталога.

#!/bin/bash
#
# Script to create md5 hashes for files in and below the current directory
# or the directory passed at the commandline
# In the first run, create the sums for all files.
# In the second run,
#  - if the files have not changed, keep the entries
#  - if the files have been deleted, forget the entry
#  - if the files have changed, create new md5 hash.
#
# Rough version - should be optimized
#

if [ $# -lt 1 ] ; then
  echo "Usage:"
  echo "$0 <hashfile> [<topdir>]"
  echo
  exit
fi

export HASHFILE=$1
export TOPDIR='.'
if [ $# -eq 2 ] ; then TOPDIR=$2; fi

export BACKFILE=$HASHFILE.bck
export TMPFILE=$HASHFILE.tmp

# In the first run, we create the file $HASHFILE if it does not exist
# You have to make sure that $HASHFILE does not contain any garbage for the first run!!

if [ ! \( -f $HASHFILE -a -s $HASHFILE \) ]; then
  echo -n "Creating $HASHFILE for the first time..."
  find $TOPDIR -type f -print0 | xargs -0 md5sum > $HASHFILE
  echo "done."
  exit
fi

# In the second run, we proceed to find the differences.
# First, find the newer files

find $TOPDIR -type f -newer $HASHFILE -print > $TMPFILE

# Now save the old file and create a new one, starting with new files

mv $HASHFILE $BACKFILE
echo -n "Processing new or modified files ..."
cat $TMPFILE | while read filename ; do
  md5sum "$filename" >> $HASHFILE
done
echo "done."

# Now walk through the old file and process to new file

cat $BACKFILE | while read md5 filename ; do
  # Does the file still exist?
  if [ -f "$filename" ] ; then
    # Has the file been modified?
    if grep -q -e "^$filename$" $TMPFILE ; then 
      echo "$filename has changed!"
    else
      echo "$md5  $filename" >> $HASHFILE
      #echo "$filename has not changed."
    fi
  else
    echo "$filename has been removed!"
  fi
done

# We now may delete temporary files
# rm $BACKFILE
# rm $TMPFILE

exit
2
ответ дан 22 May 2018 в 15:52
  • 1
    Благодарю. Я рассмотрю это после нового года, хотя и дам вам знать. На первый взгляд кажется правильным и точным. Меня не беспокоят специальные символы, поскольку файлы будут иметь один и тот же префикс, а имена состоят из цифр и букв. Жаль, однако, что md5sum не имеет возможности обновлять контрольные суммы. До сих пор, если я изменяю текстовый файл размером 50 КБ, мне нужно пересчитать контрольную сумму для всей папки 150 ГБ – Jimmy_A 29 December 2017 в 18:15
  • 2
    (1/2) Я использовал его в тестовой среде и отлично работает. Сейчас требуется намного меньше, чтобы вычислить контрольную сумму для всей папки. Однако я сделал некоторые изменения. Основная папка содержит несколько подпапок, которые идут на 3 уровня (между ними нет файлов). Каждая подпапка на нижнем уровне содержит контрольную сумму файлов в этой папке (для проверки). Теперь, когда что-то меняется в этой папке, создается новая контрольная сумма. – Jimmy_A 5 January 2018 в 13:12
  • 3
    (2/2) Содержимое каждой контрольной суммы затем помещается в главную контрольную сумму на верхнем уровне. Ему нужно немного больше QA, чтобы увидеть, есть ли проблемы в этом подходе, но он обычно работает. – Jimmy_A 5 January 2018 в 13:14

Это очень грубый сценарий, который пытается сделать то, что вы хотите. Не стесняйтесь копировать, изменять, оптимизировать - было бы неплохо иметь некоторый отклик, если он сработает для вас. Если они были протестированы в моей папке «Загрузки» и обнаружили только одну ошибку слева (имя файла, содержащее [, которое не понравилось grep).

Изменить: Изменен источник снова, поскольку создание временные метки (в первой версии) больше не нужны, поскольку новые / измененные файлы найдены с помощью find -newer. Также добавлены параметры для определения имени хэш-файла и, возможно, верхней папки для начала; поэтому сценарий не нужно вызывать из верхнего каталога.

#!/bin/bash # # Script to create md5 hashes for files in and below the current directory # or the directory passed at the commandline # In the first run, create the sums for all files. # In the second run, # - if the files have not changed, keep the entries # - if the files have been deleted, forget the entry # - if the files have changed, create new md5 hash. # # Rough version - should be optimized # if [ $# -lt 1 ] ; then echo "Usage:" echo "$0 <hashfile> [<topdir>]" echo exit fi export HASHFILE=$1 export TOPDIR='.' if [ $# -eq 2 ] ; then TOPDIR=$2; fi export BACKFILE=$HASHFILE.bck export TMPFILE=$HASHFILE.tmp # In the first run, we create the file $HASHFILE if it does not exist # You have to make sure that $HASHFILE does not contain any garbage for the first run!! if [ ! \( -f $HASHFILE -a -s $HASHFILE \) ]; then echo -n "Creating $HASHFILE for the first time..." find $TOPDIR -type f -print0 | xargs -0 md5sum > $HASHFILE echo "done." exit fi # In the second run, we proceed to find the differences. # First, find the newer files find $TOPDIR -type f -newer $HASHFILE -print > $TMPFILE # Now save the old file and create a new one, starting with new files mv $HASHFILE $BACKFILE echo -n "Processing new or modified files ..." cat $TMPFILE | while read filename ; do md5sum "$filename" >> $HASHFILE done echo "done." # Now walk through the old file and process to new file cat $BACKFILE | while read md5 filename ; do # Does the file still exist? if [ -f "$filename" ] ; then # Has the file been modified? if grep -q -e "^$filename$" $TMPFILE ; then echo "$filename has changed!" else echo "$md5 $filename" >> $HASHFILE #echo "$filename has not changed." fi else echo "$filename has been removed!" fi done # We now may delete temporary files # rm $BACKFILE # rm $TMPFILE exit
2
ответ дан 18 July 2018 в 00:15

Это очень грубый сценарий, который пытается сделать то, что вы хотите. Не стесняйтесь копировать, изменять, оптимизировать - было бы неплохо иметь некоторый отклик, если он сработает для вас. Если они были протестированы в моей папке «Загрузки» и обнаружили только одну ошибку слева (имя файла, содержащее [, которое не понравилось grep).

Изменить: Изменен источник снова, поскольку создание временные метки (в первой версии) больше не нужны, поскольку новые / измененные файлы найдены с помощью find -newer. Также добавлены параметры для определения имени хэш-файла и, возможно, верхней папки для начала; поэтому сценарий не нужно вызывать из верхнего каталога.

#!/bin/bash # # Script to create md5 hashes for files in and below the current directory # or the directory passed at the commandline # In the first run, create the sums for all files. # In the second run, # - if the files have not changed, keep the entries # - if the files have been deleted, forget the entry # - if the files have changed, create new md5 hash. # # Rough version - should be optimized # if [ $# -lt 1 ] ; then echo "Usage:" echo "$0 <hashfile> [<topdir>]" echo exit fi export HASHFILE=$1 export TOPDIR='.' if [ $# -eq 2 ] ; then TOPDIR=$2; fi export BACKFILE=$HASHFILE.bck export TMPFILE=$HASHFILE.tmp # In the first run, we create the file $HASHFILE if it does not exist # You have to make sure that $HASHFILE does not contain any garbage for the first run!! if [ ! \( -f $HASHFILE -a -s $HASHFILE \) ]; then echo -n "Creating $HASHFILE for the first time..." find $TOPDIR -type f -print0 | xargs -0 md5sum > $HASHFILE echo "done." exit fi # In the second run, we proceed to find the differences. # First, find the newer files find $TOPDIR -type f -newer $HASHFILE -print > $TMPFILE # Now save the old file and create a new one, starting with new files mv $HASHFILE $BACKFILE echo -n "Processing new or modified files ..." cat $TMPFILE | while read filename ; do md5sum "$filename" >> $HASHFILE done echo "done." # Now walk through the old file and process to new file cat $BACKFILE | while read md5 filename ; do # Does the file still exist? if [ -f "$filename" ] ; then # Has the file been modified? if grep -q -e "^$filename$" $TMPFILE ; then echo "$filename has changed!" else echo "$md5 $filename" >> $HASHFILE #echo "$filename has not changed." fi else echo "$filename has been removed!" fi done # We now may delete temporary files # rm $BACKFILE # rm $TMPFILE exit
2
ответ дан 24 July 2018 в 17:11

Другие вопросы по тегам:

Похожие вопросы: