def mount_volume(commands): if (commands.virtual_drive): # Если диск V уже занят, смонтирует диск на указаной букве virtual_drive = commands.virtual_drive else: virtual_drive = DEFAULT_VIRTUAL_DRIVE if (not virtual_drive.endswith(':')): virtual_drive = virtual_drive + ':' if (not commands.volume): return Font.YELLOW + '[!] Укажите путь к тому бэкапа' if (commands.password): if (len(commands.password) < MIN_PASSWORD_LENGTH): return Font.YELLOW + '[!] Пароль слишком короткий. Минимум 25 символов' else: return Font.YELLOW + '[!] Пароль не найден' if (utils.volume_is_mount(virtual_drive)): return Font.YELLOW + '[!] Том уже смонтирован или диск с таким именем уже существует' else: # Монтирование тома if (not utils.mount_veracrypt_volume( DEFAULT_VERACRYPT_PATH, commands.volume, commands.password, virtual_drive)): return Font.YELLOW + '[!] Возникла ошибка при монтировании тома' else: return Font.CYAN + '[>] Том успешно смонтирован'
def clearn_backup(commands): if (commands.virtual_drive): # Если диск V уже занят, смонтирует диск на указаной букве virtual_drive = commands.virtual_drive else: virtual_drive = DEFAULT_VIRTUAL_DRIVE if (not virtual_drive.endswith(':')): virtual_drive = virtual_drive + ':' if (commands.name): volume = utils.find_path_to_volume_by_backup_name(commands.name) elif (commands.volume): volume = commands.volume else: return Font.YELLOW + '[!] Введите имя бэкапа или путь к тому бэкапа для обновления' if (commands.password): if (len(commands.password) < MIN_PASSWORD_LENGTH): return Font.YELLOW + '[!] Пароль слишком короткий. Минимум 25 символов' else: return Font.YELLOW + '[!] Пароль не найден' if (utils.volume_is_mount(virtual_drive)): print(Font.YELLOW + '[!] Том уже смонтирован или диск с таким именем уже существует') else: # Монтирование тома if (not utils.mount_veracrypt_volume( DEFAULT_VERACRYPT_PATH, commands.volume, commands.password, virtual_drive)): return Font.YELLOW + '[!] Возникла ошибка при монтировании тома' print(Font.YELLOW + '[i] Загрузка старых метаданных...') try: backup_metadata = utils.load_metadata_from_json( os.path.join(virtual_drive, 'metadata.json')) except utils.CastomException as exc: return exc metadata = backup_metadata['metadata'] backup_name = backup_metadata['backup_name'] compression_level = backup_metadata['compression_level'] amount_files_in_backup = backup_metadata['amount_files_in_backup'] # Создание списка актуальных файлов и папок currency_files = [] for filename in metadata: if (not metadata[filename]['is_deleted']): currency_files.append(filename) unique_files_name = [] for filename in currency_files: file_metadata = metadata.get(filename) if (file_metadata): unique_files_name.append(file_metadata['ufn']) amount_deleted_files = amount_files_in_backup - len(currency_files) if (utils.count_deleted_files(metadata) / amount_files_in_backup * 100 > MIN_PERCENT_GARBAGE): backup_metadata.update({ 'last_update': time.ctime(time.time()), 'amount_appended_filse': 0, 'amount_updated_files': 0, 'amount_deleted_files': amount_deleted_files, 'amount_files_in_backup': amount_files_in_backup - amount_deleted_files, 'metadata': metadata, }) # Запуск очистки архива utils.clearn_backup(unique_files_name, backup_name, virtual_drive, Font) print(Font.YELLOW + '[i] Удалено файлов: %i' % amount_deleted_files) update_backup_metadata(virtual_drive, backup_metadata) print(Font.YELLOW + '[i] Начало размонтирования тома...') utils.dismount_veracrypt_volume(DEFAULT_VERACRYPT_PATH, virtual_drive) return Font.CYAN + '[>] Очистка успешно завершена!' else: return Font.YELLOW + '[i] Очистка не требуеться!'
def extract_backup(commands): if (commands.virtual_drive): # Если диск V уже занят, смонтирует диск на указаной букве virtual_drive = commands.virtual_drive else: virtual_drive = DEFAULT_VIRTUAL_DRIVE if (not virtual_drive.endswith(':')): virtual_drive = virtual_drive + ':' if (commands.name): volume = utils.find_path_to_volume_by_backup_name( commands.name, program_directory) elif (commands.volume): volume = commands.volume else: return Font.YELLOW + '[!] Введите имя бэкапа или путь к тому бэкапа для обновления' if (commands.password): if (len(commands.password) < MIN_PASSWORD_LENGTH): return Font.YELLOW + '[!] Пароль слишком короткий. Минимум 25 символов' else: return Font.YELLOW + '[!] Пароль не найден' if (not commands.path_to_save): return Font.YELLOW + '[!] Укажите путь для разархивирования бэкапа' if (utils.volume_is_mount(virtual_drive)): print(Font.YELLOW + '[!] Том уже смонтирован или диск с таким именем уже существует') else: # Монтирование тома if (not utils.mount_veracrypt_volume(DEFAULT_VERACRYPT_PATH, volume, commands.password, virtual_drive)): return Font.YELLOW + '[!] Возникла ошибка при монтировании тома' # Проверка смонтированого тома на наличие нужных файлов бэкапа if (not utils.is_backup_drive(virtual_drive)): return Font.YELLOW + '[i] Диск не является бэкапом' print(Font.YELLOW + '[i] Загрузка метаданных...') try: backup_metadata = utils.load_metadata_from_json( os.path.join(virtual_drive, 'metadata.json')) except utils.CastomException as exc: return exc files_metadata = backup_metadata['metadata'] backup_name = backup_metadata['backup_name'] common_path = backup_metadata['common_path'] path_to_extract = commands.path_to_save filelist = [] for filename in files_metadata: file = files_metadata[filename] if (not file['is_deleted']): if (file['has_parent']): parent = files_metadata[file['parent']] if (parent['has_parent']): file_ufn = files_metadata[parent['parent']]['ufn'] else: file_ufn = parent['ufn'] else: file_ufn = file['ufn'] if (file['is_dir']): filelist.append((file_ufn, file['parent_dir_name'])) else: filelist.append((file_ufn, filename[len(common_path):])) print(Font.YELLOW + '[i] Начало извлечения!') utils.extract_files(virtual_drive, backup_name, filelist, path_to_extract, Font) # Удаляем нашу костыльную папку shutil.rmtree(os.path.join(path_to_extract, 'ignore')) print(Font.YELLOW + '[i] Извлечение файлов окончено!') print(Font.YELLOW + '[i] Начало размонтирования тома...') utils.dismount_veracrypt_volume(DEFAULT_VERACRYPT_PATH, virtual_drive) return Font.CYAN + '[>] Бэкап успешно распакован'
def update_backup(commands): if (commands.virtual_drive): # Если диск V уже занят, смонтирует диск на указаной букве virtual_drive = commands.virtual_drive else: virtual_drive = DEFAULT_VIRTUAL_DRIVE if (not virtual_drive.endswith(':')): virtual_drive = virtual_drive + ':' if (commands.name): volume = utils.find_path_to_volume_by_backup_name( commands.name, program_directory) elif (commands.volume): volume = commands.volume else: return Font.YELLOW + '[!] Введите имя бэкапа или путь к тому бэкапа для обновления' if (commands.password): if (len(commands.password) < MIN_PASSWORD_LENGTH): return Font.YELLOW + '[!] Пароль слишком короткий. Минимум 25 символов' else: return Font.YELLOW + '[!] Пароль не найден' if (utils.volume_is_mount(virtual_drive)): print(Font.YELLOW + '[!] Том уже смонтирован или диск с таким именем уже существует') else: # Монтирование тома if (not utils.mount_veracrypt_volume(DEFAULT_VERACRYPT_PATH, volume, commands.password, virtual_drive)): return Font.YELLOW + '[!] Возникла ошибка при монтировании тома' # Проверка смонтированого тома на наличие нужных файлов бэкапа if (not utils.is_backup_drive(virtual_drive)): return Font.YELLOW + '[i] Диск не является бэкапом' print(Font.YELLOW + '[i] Загрузка старых метаданных...') try: backup_metadata = utils.load_metadata_from_json( os.path.join(virtual_drive, 'metadata.json')) except utils.CastomException as exc: return Font.YELLOW + exc except Exception as exc: return Font.YELLOW + '[!] Возникла непредвиденая ошибка: %s' % exc metadata = backup_metadata['metadata'] backup_name = backup_metadata['backup_name'] backup_directory = backup_metadata['directory'] compression_level = backup_metadata['compression_level'] amount_files_in_backup = backup_metadata['amount_files_in_backup'] last_filelist = utils.read_file(os.path.join( virtual_drive, 'filelist.txt')) # Загрузка старого списка файлов if (commands.blacklist): blacklist = utils.read_file(commands.blacklist) else: blacklist = utils.read_file( os.path.join(virtual_drive, 'blacklist.txt')) # Загрузка старого черного списка if (commands.recursion_level): max_recursion_level = commands.recursion_level else: max_recursion_level = backup_metadata['recursion_level'] ''' ЗАГРУЗКА СТАРЫХ И ПОЛУЧЕНИЕ НОВЫХ ДАННЫХ, ИХ СРАВНИВАНИЕ, ОТСЛЕЖИВАНИЕ ТИПА ИЗМЕНЕНИЙ И РАСПРЕДИЛЕНИЕ ИХ ПО СООТВЕТСТВУЮЩИХ СПИСКАХ''' print(Font.YELLOW + '[i] Начало сбора данных...') # Получение списка файлов находящихся в папке бэкапа new_filelist = collect_backup_files(backup_directory, blacklist, max_recursion_level) print(Font.YELLOW + '[i] Найдено файлов: %i шт.' % len(new_filelist)) # Сравнивание списков файло для поика изменений deleted_files, appended_files = utils.cmp_lists(last_filelist, new_filelist) # КОСТЫЛЬ. Удаляем со списка удаленных нашу "подставную папку" посколькуон находиться в директории программы # а не в директории для архивации, что в свою очередь скрипт расценит это как удаление файла if (IGNORED_EMPTY_DIR in deleted_files): deleted_files.remove(IGNORED_EMPTY_DIR) # Отслеживание типа изменений и также изменение списка удаленных файлов changes_list = utils.identify_changes(metadata, appended_files, deleted_files) # Добавление метаданных новых файлов for change in changes_list: parent, filename, status = change if (not parent and not status): metadata.update({filename: get_information(filename)}) # Проверка на наличие обновлений только существующих файлов с архива updated_files = [] for filename in metadata: if (os.path.exists(filename)): if (os.stat(filename).st_mtime > metadata[filename]['st_mtime']): updated_files.append(filename) metadata.update({filename: get_information(filename)}) if (commands.verbosity): print(Font.GREEN + '[>] Файл %s нужно обновить' % filename) for data in changes_list: if (all(data)): updated_files.append(data[0]) if (commands.verbosity): print(Font.GREEN + '[>] Файл %s %s в %s' % (data[0], CHANGES_STATUSES.get(data[2], 'Неизвестно'), data[1])) for file in deleted_files: if (commands.verbosity): print(Font.GREEN + '[>] Файл %s был удален!' % file) '''КОНЕЦ ЭТОГО БЛОКА''' # Поик копий, перемещений и переименований файлов для создания зависимостей для уменьшения appended_files = optimize_metadata(changes_list, metadata) amount_appended_files = len(appended_files) amount_updated_files = len(updated_files) amount_deleted_files = len(deleted_files) amount_changes = amount_updated_files + amount_appended_files + amount_deleted_files if (amount_changes >= MIN_AMOUNT_CHANGES_TO_UPDATE or commands.force): if (amount_appended_files > 0): print(Font.CYAN + '[i] Добавлено файлов: %i шт.' % amount_appended_files) if (amount_updated_files > 0): print(Font.CYAN + '[i] Обновлено файлов: %i шт.' % amount_updated_files) if (amount_deleted_files): print(Font.CYAN + '[i] Удалено файлов: %i шт.' % amount_deleted_files) # Создание папки для бэкапа utils.create_if_not_exists(os.path.join(virtual_drive, 'updates')) # Если будем делать обновление бэкапа, сохраняем старые данные и список изменений для возможности отката изменений updates_directory = os.path.join( virtual_drive, 'updates', time.ctime(time.time()).replace(':', '-')) # Проверка наличия папки для сохранения старых метаданных utils.create_if_not_exists(updates_directory) # Сохранение, старых метаданных. Зачем? Хз :D try: utils.dump_metadata_to_json( os.path.join(updates_directory, 'metadata.json'), backup_metadata) utils.dump_metadata_to_txt( os.path.join(updates_directory, 'filelist.txt'), last_filelist) utils.dump_metadata_to_json( os.path.join(updates_directory, 'changes.json'), changes_list) except utils.CastomException as exc: print(Font.YELLOW + exc) # Обновление файлов в архиве if (updated_files): asigned_updated_files = utils.asign_unf(updated_files, metadata) utils.update_files(virtual_drive, backup_name, compression_level, asigned_updated_files, Font) # Добавление новых файлов в архив if (appended_files): asigned_appended_files = utils.asign_unf(appended_files, metadata) utils.compress_files(virtual_drive, backup_name, compression_level, asigned_appended_files, Font) # Запись в метаданные метки, что файл удален if (deleted_files): utils.set_flags_is_deleted_files(metadata, deleted_files) backup_metadata.update({ 'last_update': time.ctime(time.time()), 'amount_appended_filse': amount_appended_files, 'amount_updated_files': amount_updated_files, 'amount_deleted_files': amount_deleted_files, 'amount_files_in_backup': amount_files_in_backup + amount_appended_files - amount_deleted_files, 'metadata': metadata, }) update_backup_metadata(virtual_drive, backup_metadata, new_filelist, blacklist) auto_dismount_veracrypt_volume_or_open_backup_drive( commands, virtual_drive) return Font.CYAN + '[>] Бэкап успешно обновлен!' else: return Font.YELLOW + '[!] Бэкап не требует обовления'
def create_backup(commands): if (commands.virtual_drive): # Если диск V уже занят, смонтирует диск на указаной букве virtual_drive = commands.virtual_drive else: virtual_drive = DEFAULT_VIRTUAL_DRIVE if (not virtual_drive.endswith(':')): virtual_drive = virtual_drive + ':' if (commands.auto_create_volume_by): path_to_save_new_volume = commands.auto_create_volume_by if (not commands.volume): return Font.YELLOW + '[!] Укажите путь к тому бэкапа' if (commands.password): if (len(commands.password) < MIN_PASSWORD_LENGTH): return Font.YELLOW + '[!] Пароль слишком короткий. Минимум 25 символов' else: return Font.YELLOW + '[!] Пароль не найден' if (not commands.name): return Font.YELLOW + '[!] Введите имя бэкапа' if (not commands.directory) or (not os.path.exists(commands.directory)): return Font.YELLOW + '[!] Введите путь к директории для архивации' if (commands.blacklist): try: blacklist = utils.read_file(commands.blacklist) except: blacklist = [] else: blacklist = [] if (commands.recursion_level): max_recursion_level = commands.recursion_level else: max_recursion_level = DEFAULT_MAX_RECURSION_LEVEL if max_recursion_level > 1000: sys.setrecursionlimit(max_recursion_level) if (commands.compression_level): compression_level = commands.compression_level else: compression_level = 0 print(Font.YELLOW + '[i] Начало сбора данных...') filelist = collect_backup_files(commands.directory, blacklist, max_recursion_level) # filelist.insert(0, IGNORED_EMPTY_DIR) files_metadata = collect_files_metadata(filelist) common_path = os.path.commonpath( filelist[1:] ) + '\\' #Пропускаем нулевой елемент списка, посколь он являеться нашей подставной папкой amount_files = len(filelist) print(Font.YELLOW + '[i] Найдено файлов: %i шт.' % amount_files) # Автоматически создаст новый том, если указан параметр --auto_reate_volume_by и путь для его размещения if (commands.auto_create_volume_by): volume_size = utils.count_files_size(metadata) * 1.5 # На вырост :D if (not utils.create_veracrypt_volume( DEFAULT_VERACRYPT_PATH, path_to_save_new_volume, volume_size, commands.password)): return Font.YELLOW + '[!] Возникла ошибка при создании тома' if (utils.volume_is_mount(virtual_drive)): print(Font.YELLOW + '[!] Том уже смонтирован или диск с таким именем уже существует') else: # Монтирование тома if (not utils.mount_veracrypt_volume( DEFAULT_VERACRYPT_PATH, commands.volume, commands.password, virtual_drive)): return Font.YELLOW + '[!] Возникла ошибка при монтировании тома' if (utils.is_backup_drive(virtual_drive)): return Font.YELLOW + '[!] Этой коммандой невозможно обновить уже сучествующий бэкап' # Отслеживание типа изменений stat_list = utils.identify_changes(files_metadata, filelist, []) # Поик копий файлов, для уменьшения количества файло добавляемых в архив, для уменьшения веса архива # и уменьшения время на архивирование данных unique_files_list_to_compress = optimize_metadata(stat_list, files_metadata) # Добавление файлов в которых есть дочерние файлы for filename in files_metadata: if (files_metadata[filename]['has_child']): unique_files_list_to_compress.append(filename) if (commands.verbosity): for data in stat_list: if (all(data)): print(Font.GREEN + '[>] Файл %s %s в %s' % (data[0], CHANGES_STATUSES.get(data[2], 'Неизвестно'), data[1])) duplication_percentage = 100 - (len(unique_files_list_to_compress) / amount_files * 100) asigned_files_list = utils.asign_unf(unique_files_list_to_compress, files_metadata) print(Font.CYAN + '[i] Процент дублирования данных: %i%%' % duplication_percentage) # Добавление УНИКАЛЬНЫХ файлов в архив utils.compress_files(virtual_drive, commands.name, compression_level, asigned_files_list, Font) backup_metadata = { 'backup_name': commands.name, 'directory': commands.directory, 'recursion_level': max_recursion_level, 'created': time.ctime(time.time()), 'compression_level': compression_level, 'last_update': time.ctime(time.time()), 'common_path': common_path, 'amount_files_in_backup': amount_files, 'duplication_percentage': duplication_percentage, 'metadata': files_metadata } # update_backup_metadata(virtual_drive, backup_metadata, filelist, blacklist) # Если указан флажок -а/--anonymous, имя и путь к бэкапу не будут сохранеятся в файле лежащем в корневом каталоге программы # Данный файл нужен для получения доступа к тому бэкапа по его имени if (not commands.anonymous): # Добавление имени бэкапа и пути к тому, для дельнейшего доступа к бэкапу по его имени utils.append_backup_name_to_catalog({commands.name: commands.volume}, program_directory) auto_dismount_veracrypt_volume_or_open_backup_drive( commands, virtual_drive) # Сбрасываем установленый лимит рекурсии на базовый sys.setrecursionlimit(1000) return Font.CYAN + '[i] Бэкап успешно создан'
def get_file_from_backup(commands): if (commands.virtual_drive): # Если диск V уже занят, смонтирует диск на указаной букве virtual_drive = commands.virtual_drive else: virtual_drive = DEFAULT_VIRTUAL_DRIVE if (not virtual_drive.endswith(':')): virtual_drive = virtual_drive + ':' if (commands.name): volume = utils.find_path_to_volume_by_backup_name(commands.name) elif (commands.volume): volume = commands.volume else: return Font.YELLOW + '[!] Введите имя бэкапа или путь к тому бэкапа для обновления' if (commands.password): if (len(commands.password) < MIN_PASSWORD_LENGTH): return Font.YELLOW + '[!] Пароль слишком короткий. Минимум 25 символов' else: return Font.YELLOW + '[!] Пароль не найден' if (not commands.unique_filename) and (not commands.filename) and ( not commands.shahash): return Font.YELLOW + '[i] Укажите уникальное имя файла, его хэш или уникальное имя в архиве(ufn)' if (not commands.path_to_save): return Font.YELLOW + '[i] Укажите куда нужно распаковать файл' if (utils.volume_is_mount(virtual_drive)): print(Font.YELLOW + '[!] Том уже смонтирован или диск с таким именем уже существует') else: # Монтирование тома if (not utils.mount_veracrypt_volume(DEFAULT_VERACRYPT_PATH, volume, commands.password, virtual_drive)): return Font.YELLOW + '[!] Возникла ошибка при монтировании тома' # Проверка смонтированого тома на наличие нужных файлов бэкапа if (not utils.is_backup_drive(virtual_drive)): return Font.YELLOW + '[i] Диск не является бэкапом' print(Font.YELLOW + '[i] Загрузка метаданных...') try: backup_metadata = utils.load_metadata_from_json( os.path.join(virtual_drive, 'metadata.json')) except utils.CastomException as exc: return exc files_metadata = backup_metadata['metadata'] backup_name = backup_metadata['backup_name'] if (commands.unique_filename): file_ufn = commands.unique_filename.lower() else: file_ufn = None if (commands.shahash): file_hash = commands.shahash.lower() else: file_hash = None if (commands.filename): filename = commands.filename else: filename = None for filename in files_metadata: file = files_metadata[filename] if (file_ufn) and (file_ufn == file['ufn']): print(Font.CYAN + '[i] Имя файла: %s\tразмер: %s' % (file['name'], utils.normilize_size(file['st_size']))) if (file['has_parent']): file_ufn = files_metadata[file['parent']]['ufn'] utils.extract_files(virtual_drive, backup_name, [file_ufn], commands.path_to_save, Font) # Переименование файла до начального имени os.rename(os.path.join(commands.path_to_save, file_ufn), os.path.join(commands.path_to_save, file['name'])) break # Просто выходит с цыкла, поскольку unf уникален, а значит можно вытащить только один файл смысл крутиться в цыкле? :D elif (filename) and (filename == file['name']): print(Font.CYAN + '[i] Размер: %s\t ufn: %s' % (utils.normilize_size(file['st_size']), file['ufn'])) extract_files(virtual_drive, backup_name, [file['ufn']], os.path.join(commands.path_to_save, file['name']), Font) break # Выход с цыкла нужен для того чтобы избежать, повторного разархивирования файла с бэкапа, поскольку МОЖУТ иметься данные о нескольких одинаковых файлах elif (file_hash) and (file_hash == file['hash']): print(Font.CYAN + '[i] Имя файла: %s\tразмер: %s\t ufn: %s' % (file['name'], utils.normilize_size(file['st_size']), file['ufn'])) extract_files(virtual_drive, backup_name, [file['ufn']], os.path.join(commands.path_to_save, file['name']), Font) break else: return Font.YELLOW + '[i] Файл не найден' print(Font.YELLOW + '[i] Начало размонтирования тома...') utils.dismount_veracrypt_volume(DEFAULT_VERACRYPT_PATH, virtual_drive) return Font.CYAN + '[>] Файл успешно разархивирован'
def find_file_in_backup(commands): if (commands.virtual_drive): # Если диск V уже занят, смонтирует диск на указаной букве virtual_drive = commands.virtual_drive else: virtual_drive = DEFAULT_VIRTUAL_DRIVE if (not virtual_drive.endswith(':')): virtual_drive = virtual_drive + ':' if (commands.name): volume = utils.find_path_to_volume_by_backup_name(commands.name) elif (commands.volume): volume = commands.volume else: return Font.YELLOW + '[!] Введите имя бэкапа или путь к тому бэкапа для обновления' if (commands.password): if (len(commands.password) < MIN_PASSWORD_LENGTH): return Font.YELLOW + '[!] Пароль слишком короткий. Минимум 25 символов' else: return Font.YELLOW + '[!] Пароль не найден' if (not commands.shahash and not commands.extention and commands.expression): return Font.YELLOW + '[i] Введите хэш, расширение или регулярное выражение для поска файла' if (utils.volume_is_mount(virtual_drive)): print(Font.YELLOW + '[!] Том уже смонтирован или диск с таким именем уже существует') else: # Монтирование тома if (not utils.mount_veracrypt_volume(DEFAULT_VERACRYPT_PATH, volume, commands.password, virtual_drive)): return Font.YELLOW + '[!] Возникла ошибка при монтировании тома' # Проверка смонтированого тома на наличие нужных файлов бэкапа if (not utils.is_backup_drive(virtual_drive)): return Font.YELLOW + '[i] Диск не является бэкапом' if (commands.path_to_save): out = open(commands.path_to_save, mode='w') else: out = sys.stdout print(Font.YELLOW + '[i] Загрузка метаданных...') try: backup_metadata = utils.load_metadata_from_json( os.path.join(virtual_drive, 'metadata.json')) except utils.CastomException as exc: return exc files_metadata = backup_metadata['metadata'] example = '[i] Для извлечения файла используйте комманду: --get -ufn %s -to <путь для извлечения>' for filename in files_metadata: file_metadata = files_metadata[filename] # Поиск файла по хэшу if (commands.shahash): if commands.shahash.lower() == file_metadata['hash']: print(Font.CYAN + utils.file_info(file_metadata), file=out) if (commands.verbosity): print(Font.YELLOW + example % file_metadata['ufn'], file=out) # Поиск подобных файлов по расширению if (commands.extention): if (file_metadata['name'].endswith(commands.extention.lower())): print(Font.CYAN + utils.file_info(file_metadata), file=out) if (commands.verbosity): print(Font.YELLOW + example % file_metadata['ufn'], file=out) # Поиск подобных файлов по расширению if (commands.expression): if (re.search(commands.expression, file_metadata['name'])): print(Font.CYAN + utils.file_info(file_metadata), file=out) if (commands.verbosity): print(Font.YELLOW + example % file_metadata['ufn'], file=out) if (commands.deleted): if (file_metadata['is_deleted']): print(Font.CYAN + utils.file_info(file_metadata), file=out) if (commands.verbosity): print(Font.YELLOW + example % file_metadata['ufn'], file=out) if (commands.path_to_save): print(Font.YELLOW + '[i] Результаты поика сохранены в файл: %s' % commands.path_to_save) out.close() auto_dismount_veracrypt_volume_or_open_backup_drive( commands, virtual_drive) return Font.CYAN + '[i] Поик завершен'