└── handler.py /handler.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import hashlib 4 | # import argparse 5 | 6 | 7 | # if __name__ == '__main__': 8 | # parser = argparse.ArgumentParser() 9 | # parser.add_argument("directory") 10 | # args = parser.parse_args() 11 | # 12 | # if args.directory: 13 | # os.chdir(args.directory) 14 | # for root, dirs, files in os.walk('.'): 15 | # for name in files: 16 | # print(os.path.join(root, name)) 17 | # for name in dirs: 18 | # print(os.path.join(root, name)) 19 | ################################################# 20 | def file_type(): 21 | f_type = input('\nEnter file format:\n') 22 | if f_type: 23 | return f".{f_type}" 24 | return None 25 | 26 | 27 | def sort_options(): 28 | print("\nSize sorting options:\n" 29 | "1. Descending\n" 30 | "2. Ascending\n") 31 | while True: 32 | s_option = input('Enter a sorting option:\n') 33 | if s_option in ['1', '2']: 34 | return s_option 35 | else: 36 | print('\nWrong option\n') 37 | 38 | 39 | def read_file(path_): 40 | with open(path_, 'rb') as file: 41 | return file.read() 42 | 43 | 44 | def find_in_list_of_list(list_, index_): 45 | for sub_list in list_: 46 | if index_ in sub_list: 47 | return list_.index(sub_list) 48 | 49 | 50 | def delete_files(file_list_): 51 | answer = input("\nDelete files?\n") 52 | if answer.lower() == 'no': 53 | return True 54 | elif answer.lower() == 'yes': 55 | while True: 56 | print("\nEnter file numbers to delete:") 57 | # files_delete_list = [int(x) for x in input().split()] 58 | try: 59 | files_delete_list = list(map(int, input().strip().split())) 60 | except ValueError: 61 | print("\nWrong format") 62 | else: 63 | if not len(files_delete_list) or (max(files_delete_list) > len(file_list_)): 64 | print("\nWrong format") 65 | else: 66 | space_sum = 0 67 | for num in files_delete_list: 68 | index = find_in_list_of_list(file_list_, num) 69 | os.remove(file_list_[index][1]) 70 | space_sum += file_list_[index][2] 71 | print(f'\nTotal freed up space: {space_sum} bytes') 72 | break 73 | return True 74 | else: 75 | return False 76 | 77 | 78 | def check_duplicates(files_dict_, s_type_): 79 | answer = input("\nCheck for duplicates?\n") 80 | if answer.lower() == 'no': 81 | return True 82 | elif answer.lower() == 'yes': 83 | i = 1 84 | file_list = [] 85 | for key, val in sorted(files_dict_.items(), reverse=s_type_): 86 | hash_dict = {} 87 | if len(val) > 1: 88 | print(f'\n{key} bytes') 89 | for v in val: 90 | md5 = hashlib.md5() 91 | md5.update(read_file(v)) 92 | if md5.hexdigest() in hash_dict: 93 | hash_dict[md5.hexdigest()].append(v) 94 | else: 95 | hash_dict[md5.hexdigest()] = [v] 96 | for key_, val_ in hash_dict.items(): 97 | if len(val_) > 1: 98 | print(f'Hash: {key_}') 99 | for v in val_: 100 | print(f'{i}. {v}') 101 | file_list.append([i, v, key]) 102 | i += 1 103 | while True: 104 | if delete_files(file_list): 105 | break 106 | else: 107 | print("\nWrong choice") 108 | return True 109 | else: 110 | return False 111 | 112 | 113 | def main(): 114 | files_dict = {} 115 | args = sys.argv 116 | if len(args) < 2: 117 | print('Directory is not specified') 118 | else: 119 | f_type = file_type() 120 | s_type = sort_options() 121 | os.chdir(args[1]) 122 | full_path = os.getcwd() 123 | for root, dirs, files in os.walk(full_path): 124 | for name in files: 125 | path = os.path.join(root, name) 126 | size = os.path.getsize(path) 127 | ext = os.path.splitext(path) 128 | if size in files_dict and (ext[1] == f_type or f_type is None): 129 | files_dict[size].append(path) 130 | elif ext[1] == f_type or f_type is None: 131 | files_dict[size] = [path] 132 | if s_type == '1': 133 | s_type = True 134 | elif s_type == '2': 135 | s_type = False 136 | for key, val in sorted(files_dict.items(), reverse=s_type): 137 | if len(val) > 1: 138 | print(f'\n{key} bytes') 139 | print(*val, sep='\n') 140 | while True: 141 | if check_duplicates(files_dict, s_type): 142 | break 143 | 144 | 145 | if __name__ == '__main__': 146 | main() 147 | --------------------------------------------------------------------------------