Problema
Si descargas muchos archivos pequeños (pdf, doc, xls…), lo más probable es que vayas al sitio origen a descargarlo otra vez antes que buscarlo en la carpeta Descargas. Esto, a la larga, puede resultar en una gran cantidad de archivos duplicados en el mismo directorio.
Esto puede resolverse de dos maneras:
- Manualmente: revisando los ficheros con el mismo nombre pero con una numeración entre paréntesis al final del archivo y… Bueno, si no voy a hacerlo así no sé para qué lo explico.
- Ingenierilmente: mediante un script que analice un directorio concreto de nuestro ordenador y elimine los ficheros idénticos, conservando el original.
Para hacerlo más legible y compacto, he decidido implementar el script en Python 3.5.
Solución
Los modulos a importar serán los siguientes:
from filecmp import cmp
from os import listdir
from os.path import isfile, join
Esto nos permitirá manejar funcionalidades dependientes del sistema operativo para comparar, abrir y gestionar ficheros. De manera resumida, estas son:
- filecmp.cmp(f1, f2, shallow=True): devuelve True si los ficheros f1 y f2 son idénticos.
- os.listdir(‘path’): devuelve una Lista con los nombres de los ficheros contenidos en el directorio indicado por ‘path’.
- os.path.isfile(‘path’): devuelve True si el fichero indicado por ‘path’ es un fichero real y existente y False en caso contrario.
- os.path.join(‘path_1’, ‘path_2’): une dos rutas (path). En este caso, une la ruta con el nombre del fichero, ambos pasados por parámetro.
Para empezar se introducen todos los ficheros de una localización específica (ruta) en una Lista (ficheros). Es mejor guardar la ruta del directorio en una variable, ya que se va a usar bastante a lo largo del script.
ruta = "C:/Users/Fulanito/pruebas" # por ejemplo
ficheros = [f for f in listdir("ruta") if
isfile(join("ruta", f))]
Ahora que se tienen los ficheros en una estructura de datos (Lista), se recorre comparando cada fichero con el resto.
for fichero in ficheros:
for comp in ficheros:
print(str(file) + " | " + str(comp))
En la línea 3 se imprimen los nombres de los dos ficheros que se compararán en cada iteración (fichero y comp). De esta manera podemos comprobar que está recorriendo correctamente todos los ficheros del directorio.
Para comparar se añade la función cmp()
del modulo filecmp
que recibe como argumentos los ficheros a comparar y un shallow=True
. Al igual que la ruta del directorio, almacenaremos el resultado de dicha comparación en una variable llamada veredicto.
for fichero in ficheros:
for comp in ficheros:
if ficheros != comp:
veredicto = filecmp.cmp(ruta + fichero, ruta + comp, shallow=True)
print(fichero + " | " + comp + " | " + str(veredicto))
Se ha añadido una estructura de control de flujo if
para no comparar al fichero consigo mismo. A la impresión por pantalla del anterior paso le sumamos este veredicto (booleano) para comprobar la ejecución.
Finalmente solo nos queda eliminar los duplicados tanto de la lista que habíamos creado (ficheros) como del directorio (ruta_objetivo). Para ello será necesario el uso de las funciones unlink()
del módulo os
y remove()
de la implementación de listas en Python.
for fichero in ficheros:
for comp in ficheros:
if fichero != comp:
veredicto = filecmp.cmp(ruta + fichero, ruta + comp, shallow=True)
print(file + " | " + comp + " | " + str(veredicto))
if veredicto:
print("ELIMINANDO ARCHIVO: " + comp)
only_files.remove(comp)
os.unlink(ruta + comp)
Importante: Es aconsejable ejecutar este tipo de scripts en un entorno controlado, es decir en un directorio de pruebas, antes de usarlo de forma normal. No queremos dar rienda suelta a un script que se autodestruya, no sin antes llevarse por delante el contenido del directorio analizado.
Fuente: elaboración propia.