def duplicate_finder(topdir=None): if topdir is None: topdir = os.getcwd() data = {} # rozmiar_pliku: lista plików o tym rozmiarze hashed_files = set() hashes = {} # hash: lista plików o tym samym hashu for root, dirs, files in os.walk(topdir): #print(root, dirs, files, '\n\n') for single_file in files: f_path = os.path.join(root, single_file) size = os.path.getsize(f_path) size_list = data.get(size, []) size_list.append(f_path) data[size] = size_list # TODO: policzyć hashe plików z listy if len(size_list) > 1: for file_path in size_list: if file_path not in hashed_files: f_hash = get_hash(file_path) hash_list = hashes.get(f_hash, []) hash_list.append(file_path) hashes[f_hash] = hash_list hashed_files.add(file_path) return data, hashes #, hashed_files
def duplicate_fider(topdir=None): if topdir is None: topdir = os.getcwd() # current working directory # rozmiar pliku: lista plików o tym rozmiarze data = {} hashed_files = set() # hash: lista plików o tym samym hashu hashes = {} for root, dirs, files in os.walk(topdir): #print(root, dirs, files, '\n\n') for single_file in files: f_path = os.path.join(root, single_file) size = os.path.getsize(f_path) size_list = data.get(size, []) size_list.append(f_path) data[size] = size_list #TODO: policzyć hashe plików z listy if len(size_list) > 1: # sprawdzanie czy lista jest wieksza niż 1 for file_path in size_list: if file_path not in hashed_files: f_hash = get_hash(file_path) hash_list = hashes.get(f_hash, []) hash_list.append(file_path) hashes[f_hash] = hash_list hashed_files.add(file_path) return data, hashes #, hashed_files
def duplicate_finder(topdir=None): if topdir is None: topdir = os.getcwd() data = {} hashed_files = set() hashes = {} for root, dirs, files in os.walk(topdir): #print(root, dirs, files) for single_file in files: f_path = os.path.join(root, single_file) size = os.path.getsize(f_path) size_list = data.get(size, []) size_list.append(f_path) if len(size_list) > 1: for file_path in size_list: if file_path not in hashed_files: f_hash = get_hash(file_path) size_hash_list = hashes.get(f_hash, []) size_hash_list.append(file_path) hashes[f_hash] = size_hash_list if len(size_hash_list) > 1: print( 'hash {} collision for following files:\n\t{}\n' .format(f_hash, '\n\t'.join(size_hash_list))) data[size] = size_list # TODO: PRACA DOMOWA: w tym miejscu porównać binarnie pliki, ponieważ # identyczne wartości hash nie znaczą, że pliki są identyczne # podpowiedź: https://docs.python.org/3.5/library/filecmp.html return data, hashes
def duplicate_finder(topdir=None): if topdir is None: topdir = os.getcwd() data = {} # rozmiar_pliku: lista plików o tym rozmiarze hashed_files = set() hashes = {} # hash: lista plików o tym samym hashu for root, dirs, files in os.walk(topdir): for single_file in files: f_path = os.path.join(root, single_file) size = os.path.getsize(f_path) size_list = data.get(size, []) size_list.append(f_path) data[size] = size_list if len(size_list) > 1: for file_path in size_list: if file_path not in hashed_files: f_hash = get_hash(file_path, 'sha1') hash_list = hashes.get(f_hash, []) hash_list.append(file_path) hashes[f_hash] = hash_list hashed_files.add(file_path) grouped_files = {} for hash_value, files in hashes.items(): grouped_files[hash_value] = [] for file in files: group_found = False for group in grouped_files[hash_value]: any_file_from_set = next(iter(group)) if filecmp.cmp(file, any_file_from_set, shallow=False): group.add(file) group_found = True break if not group_found: grouped_files[hash_value].append({file}) duplicates = {} for hash_value, grouped_files in grouped_files.items(): duplicates[hash_value] = [ group for group in grouped_files if len(group) > 1 ] return duplicates
def duplicate_finder(topdir=None): if topdir is None: topdir = os.getcwd() data = {} hashed_files = set() hashes = {} for root, dirs, files in os.walk(topdir): #print(root, dirs, files) for single_file in files: f_path = os.path.join(root, single_file) size = os.path.getsize(f_path) size_list = data.get(size, []) size_list.append(f_path) if len(size_list) > 1: for file_path in size_list: if file_path not in hashed_files: f_hash = get_hash(file_path) size_hash_list = hashes.get(f_hash, []) if file_path not in size_hash_list: size_hash_list.append(file_path) hashes[f_hash] = size_hash_list if len(size_hash_list) > 1: print( 'hash {} collision for following files:\n\t{}\n' .format(f_hash, '\n\t'.join(size_hash_list))) data[size] = size_list for files_to_check in hashes.values(): file_corelation = {} for file in files_to_check: file_corelation[file] = set() # Dla każdego hasha tworzę słownik {lokalizaja pliku: set plików z którymi jest powiązany) # Tworzę wszystkie możliwe pary plików i po kolei sprawdzam: # jeśli plik2 znajduje się w zbiorze wartości pliku1 to nie musze sprawdzać tylko pisze, że zachodzi kolizja # jesli nie znajduje się w zbiorze to porówuje te pliki. # W przypadku gdy pliki są identyczne to dodaję plik2 to setu pliku1, dodaję wszystkie pliki powiązane z plikiem 2 # do setu pliku1 a następnie wszystkie te wartości kopiuje do setów plików pokrewnych do pliku1. # Rozwiązanie wydaje mi się dosyć zawiłe więc chętnie poznał bym jakieś lepsze :) for file1, file2 in itertools.combinations(files_to_check, 2): if file2 not in file_corelation[file1]: if filecmp.cmp(file1, file2): file_corelation[file1].add(file2) if file_corelation[file2]: file_corelation[file1] = file_corelation[file1].union( file_corelation[file2]) for file in file_corelation[file1]: file_corelation[file] = file_corelation[file].union( file_corelation[file1]) file_corelation[file2].add(file1) print('File collision for following files:\n\t{}\n\t{}'. format(file1, file2)) else: print('File collision for following files:\n\t{}\n\t{}'.format( file1, file2)) pprint(file_corelation) return data, hashes