По-видимому, этот код стирает все файлы на Mac, а не просто дублирует код. Я не могу найти ошибку.

#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. В вашем коде вы обрабатываете каждый файл каждого каталога. Если ошибка возникает в одном файле, он пропускается, а остальные файлы каталога тоже. Это то, что я подразумеваю под «потерянным».