Определите, были ли какие-либо файлы добавлены, удалены или изменены в каталоге - PullRequest
7 голосов
/ 06 сентября 2011

Я пытаюсь написать скрипт на Python, который получит md5sum всех файлов в каталоге (в Linux).Что я считаю, я сделал в коде ниже.

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

Проблема в том, если я внесу изменение вфайл в каталоге, но затем измените его обратно.Я получаю другой результат от запуска функции ниже.(Даже если я изменил измененный файл обратно.

Может кто-нибудь объяснить это. И дайте мне знать, если вы можете подумать об обходном пути?

def get_dir_md5(dir_path):
    """Build a tar file of the directory and return its md5 sum"""
    temp_tar_path = 'tests.tar'
    t = tarfile.TarFile(temp_tar_path,mode='w')  
    t.add(dir_path)
    t.close()

    m = hashlib.md5()
    m.update(open(temp_tar_path,'rb').read())
    ret_str = m.hexdigest()

    #delete tar file
    os.remove(temp_tar_path)
    return ret_str

Редактировать: Как ответили эти замечательные люди, похоже, что tar содержит информацию заголовка, такую ​​как дата изменения. Будет ли использование zip работать по-другому или в другом формате?

Есть ли другие идеи для обхода?

Ответы [ 4 ]

8 голосов
/ 06 сентября 2011

Как уже упоминалось в других ответах, два файла tar могут отличаться, даже если их содержимое одинаково либо из-за изменений метаданных tar, либо из-за изменения порядка файлов.Вы должны запустить контрольную сумму непосредственно для данных файла, отсортировав списки каталогов, чтобы убедиться, что они всегда в одном и том же порядке.Если вы хотите включить некоторые метаданные в контрольную сумму, включите их вручную.

Непроверенный пример с использованием os.walk:

import os
import os.path
def get_dir_md5(dir_root):
    """Build a tar file of the directory and return its md5 sum"""

    hash = hashlib.md5()
    for dirpath, dirnames, filenames in os.walk(dir_root, topdown=True):

        dirnames.sort(key=os.path.normcase)
        filenames.sort(key=os.path.normcase)

        for filename in filenames:
            filepath = os.path.join(dirpath, filename)

            # If some metadata is required, add it to the checksum

            # 1) filename (good idea)
            # hash.update(os.path.normcase(os.path.relpath(filepath, dir_root))

            # 2) mtime (possibly a bad idea)
            # st = os.stat(filepath)
            # hash.update(struct.pack('d', st.st_mtime))

            # 3) size (good idea perhaps)
            # hash.update(bytes(st.st_size))

            f = open(filepath, 'rb')
            for chunk in iter(lambda: f.read(65536), b''):
                hash.update(chunk)

    return hash.hexdigest()
7 голосов
/ 06 сентября 2011

Заголовки файла TAR включают поле для измененного времени файла;изменение файла, даже если это изменение позднее будет изменено, будет означать, что заголовки файла TAR будут другими, что приведет к различным хэшам.

3 голосов
/ 06 сентября 2011

Вам не нужно создавать файл TAR, чтобы делать то, что вы предлагаете.

Вот ваш обходной алгоритм:

  1. Пройдите по дереву каталогов;
  2. Взять подпись md5 каждого файла;
  3. Сортировать подписи;
  4. Взять подпись md5 текстовой строки всех подписей отдельных файлов.

Единственная полученная подпись будет тем, что вы ищете.

Черт, тебе даже не нужен Python.Вы можете сделать это:

find /path/to/dir/ -type f -name *.py -exec md5sum {} + | awk '{print $1}'\
| sort | md5sum
1 голос
/ 06 сентября 2011
Файлы

tar содержат метаданные, превышающие фактическое содержимое файла, например время доступа к файлу, время изменения и т. Д. Даже если содержимое файла не изменяется, файл tar фактически будет другим.

...