inicio mail me! sindicaci;ón

Archive for July, 2009

Detectar ficheros duplicados con Python

Pensé que ya tenía una copia de The Little Book of Semaphores, pero por más que la buscaba no la encontraba.

Probablemente no la encontrara debido al enorme barullo que tengo en el directorio donde el aMule deposita todo lo que descarga y yo deposito todo lo que me bajo y quiero compartir.

Seguramente hubiera otro fichero con mismo contenido y distinto nombre. ¿Cómo encontrarlo?

Mediante md5sum *.pdf | sort podría revisar una por una cada entrada devuelta y buscar con un poco menos de dolor si hay algún duplicado, ya que sort ordena, pero que yo sepa no tiene una opción para mostrar sólo los duplicados (y en el manual no viene nada al respecto).

Quizá awk me ayudara, pero el caso es que hay que practicar Python (descargar fuente):

import sys
import hashlib

def do_hash(nombreFichero):
        fichero=open(nombreFichero,‘r’)
        contenido=fichero.read()
        fichero.close()
        return hashlib.md5(contenido).hexdigest()

if __name__==‘__main__’:
        hashes={}

        for fichero in sys.argv[1:]:
                clave = do_hash(fichero)
                try:
                        hashes[clave].append(fichero)
                except KeyError:
                        hashes[clave]=[fichero]

        for clave in hashes.keys():
                if len(hashes[clave])>1:
                        print ‘Same key %s for:’%(clave)
                        for fichero in hashes[clave]:
                                print \t%s’%(fichero)

Funcionamiento:

Una vez comprobado que el script se está ejecutando (__name__ == ‘__main__’), y no ha sido llamado como módulo, por cada fichero en la línea de comandos averigua su hash mediante la función do_hash (que internamente usa MD5, pero podría usar SHA1 sin más que cambiarlo).
En un diccionario se guarda por cada hash, una lista con los nombres de los ficheros que tienen la misma hash.

Posteriormente, por cada hash encontrada, si en la lista de ficheros que tienen esa hash hay más de un fichero, se imprime cada nombre de fichero, de manera que el usuario puede visualizar qué ficheros tienen el mismo contenido:

pablo@golgi:~/Desktop$ python dups.py *.pdf
Same key 3f4568dc0b3e96b94f02c0b58d57b702 for:
        tls.2.pdf
        tls.pdf
pablo@golgi:~/Desktop$ rm tls.2.pdf

Probablemente, una salida de este estilo (agrupando los ficheros iguales sin verborrea):

pablo@golgi:~/Desktop$ python dups.py *.pdf
tls.2.pdf
tls.pdf

same1_1.pdf
same1_2.pdf
same1_3.pdf
pablo@golgi:~/Desktop$ rm tls.2.pdf  same1_2.pdf  same1_3.pdf

fuera más amigable para utilizar el comando desde algún script.

Ahí queda eso, por si a alguien (o a mí mismo en el futuro) le sirve para algo.

Ideas:

  • hacerlo en bash, o al menos de una manera más simple.
  • Si no es posible, programar una opción para ello en el sort.
  • Me gustaría ver qué tal funciona la función do_hash() con ficheros enormes (de 1G., p.e.). Esto habría que arreglarlo…

dups.py