En la entrada
anterior se habló de como utilizar las funciones hash para proteger un poco más nuestros datos. En esta entrada estaremos utilizando las funciones hash para conseguir los archivos duplicados dentro de nuestro sistema.
El tema de esta entrada es simple, la temática es la siguiente: Se calcula el hash de los datos
— en este caso de cada archivo
— y se está pendiente de que dos archivos no tengan la misma función hash, de ser así, se tiene un archivo duplicado y se procede con el procesamiento deseado.
Para ejecutar el siguiente programa se necesita:
- Ruby
- La gema Mp3Info
gem install mp3info
#!/usr/bin/env ruby
# encoding: utf-8
# Program that looks for duplicate files.
# Author: MaG, http://newbieshell.blogspot.com
require 'digest/sha2'
require 'find'
require 'mp3info'
class FileRecord
attr_reader :file, :sum, :duplicates
def initialize(path, sum)
@file = path
@sum = sum
@duplicates = []
end
def has_duplicates?
not @duplicates.empty?
end
def add(path)
@duplicates.push path
end
end
if ARGV[0].nil? or not File.directory? ARGV[0]
$stderr.puts "Use: #$0 <directory>"
exit 1
end
hsh = {}
EMPTY_STRING_SUM = Digest::SHA256.hexdigest ''
Find.find(ARGV[0]) do|path|
next unless File.file? path
puts path
sum = nil
if path =~ /\.mp3$/i
begin
mp3 = Mp3Info.new(path)
pos, length = mp3.audio_content
mp3.close
rescue
next # discard this problematic file
end
File.open(path) do|file|
file.pos = pos
sum = Digest::SHA256.hexdigest(file.read(length))
end
else
sum = Digest::SHA256.file(path).hexdigest
end
next if sum == EMPTY_STRING_SUM
# nah!, let's use +unless+
unless hsh[sum]
hsh[sum] = FileRecord.new(path, sum)
else
file_record = hsh[sum]
file_record.add(path)
end
end
print "\n\nduplicates!\n\n"
hsh.each_value do|record|
next unless record.has_duplicates?
print "#{record.file}:\n->"
print record.duplicates.join("\n-> "), "\n\n"
end
Se utiliza la gema Mp3Info para
localizar el segmento de audio y calcular la función hash a dicha parte
del archivo. Se hace esto, porque es posible que
los metadatos de dos archivos varíen y de esta manera corrompan la singularidad del archivo, aun cuando dichos archivos contengan el mismo audio.
Si bien, el programa utiliza un buen algoritmo, este requiere una cantidad considerable de cálculos, los cuales son directamente proporcionales al tamaño de los archivos dentro del directorio raíz en cuestión. Pero algo si es seguro, encuentra los archivos duplicados.
Conclusión
Es posible implementar este programa en un
Shell Script utilizando la herramienta
sha256sum y el comando
find. Aunque con el
Shell será un poco más difícil contrarrestar el problema de los metadatos en los archivos de tipo: mp3, jpeg, png, pdf, etc.
Al parecer, los formatos de audio parecen ser los más propensos a este tipo de casos, donde los metadatos corrompen la función hash. Es muy importante tener esto pendiente para cuando se necesite un poco más de precisión.
Si necesitas una solución utilizando Bash, o necesitas ayuda, deja un comentario o contáctame por correo, el cual está en la parte de arriba de este blog.