Форум сайта python.su
Здравствуйте. Вкратце алгоритм - ищу дубликаты файлов - по мд5 суме записываются в один файл, и по названию - записываются в другой файл. Возможно, вы знаете другой, лучший способ навести порядок на компе, поделитесь. Но вот, то, что Я сделал (есть проблемы):
import os import sys import string import difflib import hashlib NAME_ACCURACY = 0.75 def get_disk_drives_list(): disk_list = ['%s:' % letter for letter in string.ascii_lowercase if os.path.exists('%s:' % letter)] return disk_list def get_full_filenames(path): for root, dirnames, filenames in os.walk(path): for filename in filenames: yield os.path.join(root, filename) def get_md5(filename): """ Open, close, read file and calculate MD5 on its contents """ with open(filename) as file_to_check: data = file_to_check.read() md5 = hashlib.md5(data).hexdigest() return md5 def compare_files(filename1, filename2): """ Compare files by md5 sum, if don't match - compare by names """ if filename1 != filename2: if get_md5(filename1) == get_md5(filename2): with open('md5_duplicates.txt', 'a') as md5_duplicates: md5_duplicates.write('%s\n%s\n---\n' % (filename1, filename2)) elif difflib.SequenceMatcher(None, os.path.basename(filename1), os.path.basename(filename2)).ratio() >= NAME_ACCURACY: with open('name_duplicates.txt', 'a') as name_duplicates: name_duplicates.write('%s\n%s\n---\n' % (filename1, filename2)) def find_duplicates(path): """ Search for duplicates in set path if path == '/', it means main root - search on all disk drives """ if path == '/': for disk_drive1 in get_disk_drives_list(): for filename1 in get_full_filenames(disk_drive1): for disk_drive2 in get_disk_drives_list(): for filename2 in get_full_filenames(disk_drive2): compare_files(filename1, filename2) elif os.path.exists(path): for filename1 in get_full_filenames(path): for filename2 in get_full_filenames(path): compare_files(filename1, filename2) else: '%s is wrong path' % path if __name__ == '__main__': """ Example usage: duplicates.py / duplicates.py c:/temp/ """ path = sys.argv[1] print 'Searching for duplicates in %s' % path print 'Please, wait...' find_duplicates(path) print '--- Job done ---'
Отредактировано Master_Sergius (Ноя. 11, 2013 21:30:58)
Офлайн
не гадайте, проведите отладку и сами разберетесь, заодно проконтролируете ход работы вашей программы, наверняка найдете что исправить или дополнить. Отладка делается либо средствами IDE, либо модулем pdb
Офлайн
1) Надебажил такой фокус - работает со всеми дисками, кроме того, с которого запускаю этот скрипт. Получается, если указываю этот d: - он ходит только по папке со скриптом, если же любые другие диски - c: или e: - шарит по всему диску…
2) почему-то, по мд5 сумме сходятся совершенно различные файлы, а не только те, что надо. Я понимаю, мд5 сумма может совпасть, но не в таком же большом количестве случаев!
Вот с этими двумя вещами пока что не могу справиться….
Офлайн
1) не верю.
2) тем более не верю
кроме этого - если вам на пути попадутся файлы размером с 4гб - они при подсчете тоже будут считываться полностью в память и потом считаться md5 ? Ни на какую плохую мысль не подталкивает?
Я бы вообще по другому делал, разбил бы процесс на этапы. В общем схема такая. Первый это поиск всей путей к файлам, записал бы результат в бд sqlite, подсчитал бы для каждого md5 сумму, записал в бд. Далее бы уже искал по бд идентичные параметры хеш сумм.
Офлайн
Насчёт неверия - что стоит, взять и проверить?
Но, допустим, багов там полно. Вернёмся к большим файлам. А как посчитать мд5 сумму по содержимому другим способом?
Вариант с базой данных мне нравится, но прежде чем переделать на использование бд, опять-таки - как тогда считать мд5 сумму? И может ли быть другой способ поиска дубликатов файлов, а не по мд5 сумме?
Офлайн
В документации по hashlib есть даже пример.
http://docs.python.org/2/library/hashlib.html
>>> import hashlib
>>> m = hashlib.md5()
>>> m.update("Nobody inspects")
>>> m.update(" the spammish repetition")
>>> m.digest()
'\xbbd\x9c\x83\xdd\x1e\xa5\xc9\xd9\xde\xc9\xa1\x8d\xf0\xff\xe9'
>>> m.digest_size
16
>>> m.block_size
64
И может ли быть другой способ поиска дубликатов файлов, а не по мд5 сумме?
Отредактировано cutwater (Ноя. 12, 2013 09:30:34)
Офлайн
Этот пример, с m.update() - это, получается, читать файл построчно и апдейтить хешсуму?
Кстати, насчёт размера - хороший вариант…
И последнее - можно ли как-то быстро сравнить содержимое файлов на схожесть? Ну вот, как названия файлов сравнивал с неким процентом, так чтобы быстро сравнить содержимое - или это глупая затея?
Офлайн
Master_Sergius
читать файл построчно
Master_Sergius
Ну вот, как названия файлов сравнивал с неким процентом,
In : difflib.SequenceMatcher(None, ‘DSC_4142.JPG’, ‘DSC_4143.JPG’).ratio()
Out: 0.9166666666666666
Отредактировано cutwater (Ноя. 12, 2013 12:27:09)
Офлайн
Насчёт книги по алгоритмам - согласен, можете предложить какие-нибудь. Но вот что насчёт сравнивания по содержимому файлов? Ибо ваш пример - это всё тоже сравнивание по названию, которое у меня уже запрограммировано (см. код из первого поста):
difflib.SequenceMatcher(None, os.path.basename(filename1), os.path.basename(filename2)).ratio() >= NAME_ACCURACY
Отредактировано Master_Sergius (Ноя. 12, 2013 11:47:40)
Офлайн
Намек видимо не понял.
Читать нужно по блокам (см. аргументы метода read).
Пример я привел как раз таки относительно сравнения по имени, поясняющий, что сравнивать таким образом имена файлов глупо.
Подводя итог: Как раз таки глупо сравнивать имена файлов, по содержимому сравнивать нужно.
Но при этом нужен более адекватный алгоритм.
Отредактировано cutwater (Ноя. 12, 2013 12:32:05)
Офлайн