Я фотограф и делаю много резервных копий. За эти годы я нашел себя с большим количеством жестких дисков. Теперь я купил NAS и скопировал все мои фотографии на одном рейде 3TB 1, используя rsync. По моему сценарию около 1 ТБ этих файлов дублируются. Это происходит от выполнения нескольких резервных копий, прежде чем удалять файлы на моем ноутбуке и быть очень грязными. У меня есть резервная копия всех этих файлов на старых жестких дисках, но было бы больно, если бы мой скрипт испортил вещи. Не могли бы вы взглянуть на мой дубликат сценария поиска и рассказать мне, думаете ли вы, что я могу запустить его или нет? Я попробовал его в тестовой папке, и все выглядит нормально, но я не хочу испортить NAS.Как заменить дубликаты файлов на жесткие ссылки с помощью python?
Скрипт состоит из трех шагов в трех файлах. В этой первой части я нахожу все файлы изображений и метаданных и помещаю их в базу данных полки (datenbank) с их размером в качестве ключа.
import os
import shelve
datenbank = shelve.open(os.path.join(os.path.dirname(__file__),"shelve_step1"), flag='c', protocol=None, writeback=False)
#path_to_search = os.path.join(os.path.dirname(__file__),"test")
path_to_search = "/volume1/backup_2tb_wd/"
file_exts = ["xmp", "jpg", "JPG", "XMP", "cr2", "CR2", "PNG", "png", "tiff", "TIFF"]
walker = os.walk(path_to_search)
counter = 0
for dirpath, dirnames, filenames in walker:
if filenames:
for filename in filenames:
counter += 1
print str(counter)
for file_ext in file_exts:
if file_ext in filename:
filepath = os.path.join(dirpath, filename)
filesize = str(os.path.getsize(filepath))
if not filesize in datenbank:
datenbank[filesize] = []
tmp = datenbank[filesize]
if filepath not in tmp:
tmp.append(filepath)
datenbank[filesize] = tmp
datenbank.sync()
print "done"
datenbank.close()
Вторая часть. Теперь я удаляю все размеры файлов, которые имеют только один файл в своем списке и создают другую базу данных полки с хешем md5 в качестве ключа и список файлов в качестве значения.
import os
import shelve
import hashlib
datenbank = shelve.open(os.path.join(os.path.dirname(__file__),"shelve_step1"), flag='c', protocol=None, writeback=False)
datenbank_step2 = shelve.open(os.path.join(os.path.dirname(__file__),"shelve_step2"), flag='c', protocol=None, writeback=False)
counter = 0
space = 0
def md5Checksum(filePath):
with open(filePath, 'rb') as fh:
m = hashlib.md5()
while True:
data = fh.read(8192)
if not data:
break
m.update(data)
return m.hexdigest()
for filesize in datenbank:
filepaths = datenbank[filesize]
filepath_count = len(filepaths)
if filepath_count > 1:
counter += filepath_count -1
space += (filepath_count -1) * int(filesize)
for filepath in filepaths:
print counter
checksum = md5Checksum(filepath)
if checksum not in datenbank_step2:
datenbank_step2[checksum] = []
temp = datenbank_step2[checksum]
if filepath not in temp:
temp.append(filepath)
datenbank_step2[checksum] = temp
print counter
print str(space)
datenbank_step2.sync()
datenbank_step2.close()
print "done"
И, наконец, самая опасная часть. Для ключа evrey md5 я извлекаю список файлов и делаю дополнительный sha1. Если он соответствует, я удаляю каждый файл в этом списке за исключением первого и создаю жесткую ссылку для замены удаленных файлов.
import os
import shelve
import hashlib
datenbank = shelve.open(os.path.join(os.path.dirname(__file__),"shelve_step2"), flag='c', protocol=None, writeback=False)
def sha1Checksum(filePath):
with open(filePath, 'rb') as fh:
m = hashlib.sha1()
while True:
data = fh.read(8192)
if not data:
break
m.update(data)
return m.hexdigest()
for hashvalue in datenbank:
switch = True
for path in datenbank[hashvalue]:
if switch:
original = path
original_checksum = sha1Checksum(path)
switch = False
else:
if sha1Checksum(path) == original_checksum:
os.unlink(path)
os.link(original, path)
print "delete: ", path
print "done"
Что вы думаете? спасибо.
* если это так важно: это синология 713+ и имеет файловую систему ext3 или ext4.
, а не удалять немедленно переместить дубликаты в другую папку, то удалите их всех, когда вы удовлетворены тем, что ничего не потеряно. – suspectus
К сожалению, NAS 3TB полон. У меня осталось только 20 ГБ, поэтому я должен удалить его. Кроме того, я говорю о 139.020 дублированных файлах. Я не могу контролировать вручную, что скрипт не испортил. – JasonTS
@JasonTS: Перемещение файлов в другой каталог в одной и той же файловой системе не будет тратить места, а создание жестких ссылок 128K будет тратить мегабайт или около того (вероятно, меньше, чем ваша база данных «shelve»), так что, вероятно, это не очень хорошая причина отклонить предложение подозреваемого. – abarnert