2011-09-06 17 views
7

Estoy tratando de escribir un script de Python que obtenga el md5sum de todos los archivos en un directorio (en Linux). Lo cual creo que he hecho en el código a continuación.Determinar si se han agregado, eliminado o modificado archivos en un directorio

Quiero poder ejecutar esto para asegurarme de que no haya ningún archivo dentro del directorio cambiado y que no se hayan agregado archivos para eliminar.

El problema es si realizo un cambio en un archivo en el directorio pero luego lo cambio. Obtengo un resultado diferente al ejecutar la función a continuación. (A pesar de que he cambiado de nuevo el archivo modificado

Puede alguien explicar esto y quiero saber si se puede pensar en un trabajo en torno

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 

Editar:..? A medida que estas finas personas tienen contestado, se ve como el alquitrán incluye información de cabecera como fecha de modificación. Would utilizando el trabajo postal o cualquier otro formato diferente?

cualquier otra idea para arounds de trabajo?

Respuesta

8

Como las otras respuestas mencionadas, dos archivos de alquitrán puede ser diferente incluso si los contenidos son los mismos, ya sea debido a cambios en los metadatos de alquitrán o para presentar cambios de orden. Debe ejecutar la suma de comprobación en los datos del archivo directamente, ordenando las listas de directorios para asegurarse de que estén siempre en el mismo orden. Si desea incluir algunos metadatos en la suma de comprobación, inclúyalos manualmente.

ejemplo no probado usando 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() 
+2

Gran respuesta. El mismo método básico que describí pero en código. Bonito. –

7

tAR archivo HEA los ders incluyen un campo para el tiempo modificado del archivo; el hecho de cambiar un archivo, incluso si ese cambio se cambia posteriormente, significará que los encabezados del archivo TAR serán diferentes, lo que dará lugar a hashes diferentes.

+0

Gracias. Supongo que no hay opción para decirle que no incluya los encabezados de los archivos. – Greg

+1

Incluso si pudiera, no hay garantía de que el orden de los archivos en el TAR sea consistente.Podría hacer algo que compute el hash de cada uno de los archivos en el directorio, y luego crear un hash basado en esos valores, lo que le dirá estrictamente en función del contenido de los archivos, ya sea igual o no. – Joe

1

tar archivos contienen metadatos más allá de los contenidos de los archivos reales, como los tiempos de acceso a archivos, tiempos de modificación, etc. Incluso si el contenido del archivo no cambian, el archivo tar, de hecho, ser diferente.

3

No necesita hacer que el archivo TAR haga lo que usted propone.

Aquí es su algoritmo de solución:

  1. recorrer el árbol de directorios;
  2. Tome la firma md5 de cada archivo;
  3. Ordenar las firmas;
  4. Tome la firma md5 de la cadena de texto de todas las firmas de los archivos individuales.

La única firma resultante será lo que usted está buscando.

Diablos, ni siquiera necesita Python. Usted puede hacer esto:

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