Domanda

Sto cercando di scrivere uno script Python che otterrà il md5sum di tutti i file in una directory (in Linux). Che credo che ho fatto nel seguente codice.

Voglio essere in grado di eseguire questo per assicurarsi che nessun file all'interno della directory sono cambiati, e nessun file sono stati aggiunti per cancellato.

Il problema è che se faccio una modifica a un file nella directory, ma poi cambiare di nuovo. Ottengo un risultato diverso da correre la funzione qui sotto. (Anche se ho cambiato la parte posteriore file modificato.

Qualcuno può spiegare questo. E fatemi sapere se si può pensare ad un work-around?

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

Modifica Come pagine di queste persone hanno risposto, sembra che il catrame include intestazione informazioni come data di modifica. Sarebbe utilizzando lavoro zip in modo diverso o in un altro formato?

Tutte le altre idee per arounds di lavoro?

È stato utile?

Soluzione

Come le altre risposte menzionati, due file tar può essere diverso, anche se il contenuto è lo stesso sia a causa di modifiche dei metadati di catrame o ai cambiamenti di ordine di file. È necessario eseguire il checksum sui dati di file direttamente, l'ordinamento gli elenchi delle directory per assicurarsi che siano sempre nello stesso ordine. Se si desidera includere alcuni metadati nel checksum, includere manualmente.

Non testato esempio utilizzando 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()

Altri suggerimenti

intestazioni di file TAR includono un campo per l'ora di modifica del file; l'atto di modifica di un file, anche se questo cambiamento è poi cambiato di nuovo, significherà il TAR intestazioni dei file sarà diverso, portando a diverse hash.

Non è necessario per rendere il file TAR per fare quello che proponi.

Ecco l'algoritmo soluzione:

  1. A piedi l'albero delle directory;
  2. Prendere la firma MD5 di ogni file;
  3. Ordina le firme;
  4. Prendere la firma MD5 della stringa di testo di tutte le firme dei singoli file.

Il singolo firma risultante sarà quello che stai cercando.

Heck, non hai nemmeno bisogno di Python. Si può fare questo:

find /path/to/dir/ -type f -name *.py -exec md5sum {} + | awk '{print $1}'\
| sort | md5sum

I file tar contengono metadati al di là dei contenuti dei file reali, come ad esempio i tempi di accesso ai file, tempi di modifica, ecc Anche se il contenuto del file non cambiano, il file tar sarà infatti diversa.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top