#macos #python-3.x #hash
#macos #python-3.x #хэш
Вопрос:
import os,sys
import hashlib
path = '/Users'
unique = []
count = 0
mem = 0
statinfo=0
def fun(path):
try:
dirs = os.listdir(path)
for x in dirs:
print(path '/' x)
statinfo = 0
if os.path.isdir(path '/' x):
fun(path '/' x)
elif os.path.isfile(path '/' x):
hasher = hashlib.md5()
with open(path '/' x,'rb') as afile:
buf = afile.read()
hasher.update(buf)
if hasher.hexdigest() not in unique:
unique.append(hasher.hexdigest())
else:
statinfo=os.stat(path '/' x)
global mem
mem =statinfo.st_size
os.remove(path '/' x)
global count
count =1
return
except:
pass
fun(path)
Таким образом, этот код, по-видимому, удалил все файлы на моем Macbook (к счастью, я сделал резервную копию перед запуском кода). Я запустил этот код с терминала, предоставив разрешение sudo. Чтобы устранить ошибку разрешения, возникающую в папке Dropbox, я использовал Try и Except для обработки ошибок. Я не могу найти, что пошло не так в коде.
Комментарии:
1. Рассматривали ли вы возможность предоставления ему одного тестового каталога для запуска и попытки некоторой отладки? Запуск его
/Users
, вероятно, был не лучшей идеей…2. Перед запуском в /Users я попробовал использовать одну папку, изменив имя пути. Это сработало идеально. Но когда я запустил его в / Users , это произошло.
Ответ №1:
Проанализировать
У вас есть рекурсивный вызов для каждой папки из /Users
пути.
Для каждого файла вы вычисляете сумму md5
- Если md5 еще не существует: вы сохраняете его в списке,
- В противном случае вы удаляете файл.
Но, если у вас есть исключение, например, «Отказано в разрешении», вы выходите из функции (некоторые файлы / каталоги теряются).
Ваш код не очень защищен:
- например, суммы md5 недостаточно для проверки дубликатов: все пустые файлы являются дубликатами. Вы можете использовать
filecmp
для сравнения файлов. - Вы анализируете все каталоги, даже скрытые.
- Что насчет символических ссылок?
Предложение
Однако вы можете попробовать что-то более понятное:
import hashlib
import os
# Note that sometimes you won't be able to fit the whole file in memory.
# In that case, you'll have to read chunks of 4096 bytes sequentially
# and feed them to the Md5 function:
def md5(fname):
hash_md5 = hashlib.md5()
with open(fname, "rb") as f:
for chunk in iter(lambda: f.read(4096), b""):
hash_md5.update(chunk)
return hash_md5.hexdigest()
def find_duplicates(work_dir):
found = {}
for root, dirnames, filenames in os.walk(work_dir):
for filename in filenames:
file_path = os.path.join(root, filename)
try:
hexdigest = md5(file_path)
if hexdigest in found:
print("Duplicate of: " found[hexdigest])
yield file_path
else:
found[hexdigest] = file_path
except IOError as exc:
print(exc)
def remove_duplicates(path):
for file_path in find_duplicates(path):
print("remove: " file_path)
os.remove(file_path)
if __name__ == '__main__':
remove_duplicates('/Users')
Комментарии:
1. «Но, если у вас есть исключение, например, «Отказано в разрешении», вы выходите из функции (некоторые файлы / каталоги теряются)». Но как? Не будет ли файл пропускаться при возникновении ошибки?
2. В вашем коде вы обрабатываете каждый файл каждого каталога. Если ошибка возникает в одном файле, он пропускается, а остальные файлы каталога тоже. Это то, что я подразумеваю под «потерянным».