From dbca17593bd0c5adc09803f30185ee36486dd07d Mon Sep 17 00:00:00 2001 From: Hansjakob Florian Date: Fri, 6 Feb 2026 17:27:28 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E6=96=87=E4=BB=B6=E8=87=B3?= =?UTF-8?q?=20/?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- integrated_tool_test.py | 432 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 432 insertions(+) create mode 100644 integrated_tool_test.py diff --git a/integrated_tool_test.py b/integrated_tool_test.py new file mode 100644 index 0000000..076c484 --- /dev/null +++ b/integrated_tool_test.py @@ -0,0 +1,432 @@ +import os +import shutil +import sys +import pathlib +import subprocess +from io import BytesIO + +current_mode = None + +def force_close_handles(folder_path): + try: + import psutil + closed_count = 0 + + for proc in psutil.process_iter(['pid', 'name']): + try: + for item in proc.open_files(): + if folder_path.lower() in item.path.lower(): + proc.kill() + closed_count += 1 + print(f"[系统] 已关闭占用进程: {proc.info['name']} (PID: {proc.info['pid']})") + break + except (psutil.NoSuchProcess, psutil.AccessDenied): + pass + + if closed_count > 0: + import time + time.sleep(0.5) + + return closed_count > 0 + except ImportError: + return False + + + + +def delete_system_files(folder_path): + system_files = ['thumbs.db', 'desktop.ini', '.ds_store', 'thumbs.db:encryptable'] + deleted_count = 0 + + try: + for root, dirs, files in os.walk(folder_path): + for filename in files: + if filename.lower() in system_files or filename.startswith('._'): + file_path = os.path.join(root, filename) + try: + os.chmod(file_path, 0o777) + os.remove(file_path) + deleted_count += 1 + except: + pass + + if deleted_count > 0: + print(f"[系统] 已清理 {deleted_count} 个系统隐藏文件") + except: + pass + + +def get_next_log_index(): + index = 1 + while pathlib.Path(f"path_list_{index}.log").exists(): + index += 1 + return index + + +def open_folder(path: pathlib.Path): + if sys.platform.startswith("win"): + os.startfile(path) + elif sys.platform.startswith("darwin"): + subprocess.run(["open", path]) + else: + subprocess.run(["xdg-open", path]) + +def mode_wb(): + print("\n" + "="*60) + print("已进入 WB 模式 - 文件夹批处理工具") + print("功能:复制文件夹 -> 重命名文件夹和内部文件 -> 标记原文件夹") + print("="*60) + + while True: + print("\n================== 新的工作任务 ==================") + work_dir = input("请输入主文件夹路径 (工作路径, 输入 :back 返回): ").strip() + + if work_dir == ":back": + return + + if not os.path.exists(work_dir): + print(f"[错误] 工作路径 '{work_dir}' 不存在,请先创建或检查路径。") + continue + + print(f"[系统] 已锁定工作路径: {work_dir}") + + process_wb_folder(work_dir) + + print("\n------------------------------------------------------") + while True: + choice = input("任务结束。输入 :back 返回主菜单,或输入 :y 开启下一个工作路径: ").strip().lower() + if choice == ":back": + return + elif choice == ":y": + break + else: + print("输入无效,请输入 :back 或 :y") + + +def process_wb_folder(work_dir): + while True: + print("\n------------------------------------------------------") + src_path_input = input("请输入待复制的文件夹路径 (输入 :end 结束当前阶段): ").strip() + + if src_path_input == ":end": + return + + if not os.path.exists(src_path_input): + print(f"[错误] 路径 '{src_path_input}' 不存在,请重新输入。") + continue + + target_name = input("请输入想要重命名的名称: ").strip() + if not target_name: + print("[错误] 名称不能为空。") + continue + + dest_path = os.path.join(work_dir, target_name) + + try: + if os.path.exists(dest_path): + print(f"[错误] 目标文件夹 '{dest_path}' 已经在工作路径下存在,跳过此任务。") + continue + + shutil.copytree(src_path_input, dest_path) + print(f"[成功] 文件夹已复制并重命名为: {target_name}") + + all_items = os.listdir(dest_path) + files = [] + for f in all_items: + full_path = os.path.join(dest_path, f) + if os.path.isfile(full_path) and not f.startswith('.') and f.lower() not in ['thumbs.db', 'desktop.ini']: + files.append(f) + + files.sort() + + count = 1 + for filename in files: + file_ext = os.path.splitext(filename)[1] + new_filename = f"{target_name} {count}{file_ext}" + + old_file_path = os.path.join(dest_path, filename) + new_file_path = os.path.join(dest_path, new_filename) + + os.rename(old_file_path, new_file_path) + count += 1 + + print(f"[成功] 已重命名文件夹内的 {count-1} 个文件 (从 1 开始)。") + + clean_src_path = os.path.normpath(src_path_input) + parent_dir = os.path.dirname(clean_src_path) + original_folder_name = os.path.basename(clean_src_path) + new_src_folder_name = "used_" + original_folder_name + used_src_path = os.path.join(parent_dir, new_src_folder_name) + + try: + delete_system_files(clean_src_path) + + os.rename(clean_src_path, used_src_path) + print(f"[成功] 原文件夹已重命名为: {new_src_folder_name}") + except PermissionError: + print(f"[警告] 文件夹被占用,尝试强制解锁...") + if force_close_handles(clean_src_path): + try: + os.rename(clean_src_path, used_src_path) + print(f"[成功] 原文件夹已重命名为: {new_src_folder_name}") + except Exception as e: + print(f"[警告] 解锁后仍无法重命名: {e}") + print(f" 原文件夹路径: {clean_src_path}") + else: + print(f"[警告] 无法重命名原文件夹为 used_ 开头(需要安装psutil库)") + print(f" 安装命令: python.exe -m pip install psutil --break-system-packages") + print(f" 原文件夹路径: {clean_src_path}") + except FileExistsError: + print(f"[警告] 目标名称 '{new_src_folder_name}' 已存在,跳过重命名") + except Exception as e: + print(f"[警告] 重命名原文件夹时出错: {e}") + + except PermissionError: + print(f"[错误] 权限不足,无法访问或复制文件夹") + except Exception as e: + print(f"[异常] 发生未知错误: {e}") + + +def mode_path(): + print("\n" + "="*60) + print("已进入 PATH 模式 - 文件夹批量创建工具") + print("操作指南:") + print("1. 输入路径后按回车 -> 加入待创建队列") + print("2. 输入 ':y' 并回车 -> 立即批量创建队列中所有文件夹") + print("3. 输入 ':open x' -> 打开 path_list_x.log 中的所有文件夹") + print("4. 输入 ':back' -> 返回主菜单") + print("="*60 + "\n") + + path_queue = [] + + while True: + queue_count = len(path_queue) + prompt = f"[{queue_count} 个待创建] >>> 请输入路径: " + raw_path = input(prompt).strip() + + if raw_path.lower().startswith(":open"): + parts = raw_path.split() + if len(parts) != 2 or not parts[1].isdigit(): + print("用法错误,应为 :open x") + continue + + log_index = parts[1] + log_file = pathlib.Path(f"path_list_{log_index}.log") + + if not log_file.exists(): + print(f"日志文件不存在: {log_file}") + continue + + print(f"正在打开 {log_file} 中的文件夹...") + with log_file.open("r", encoding="utf-8") as f: + for line in f: + folder = pathlib.Path(line.strip()) + if folder.exists(): + open_folder(folder) + else: + print(f"路径不存在,已跳过: {folder}") + continue + + if raw_path.lower() == ':y': + if not path_queue: + print("警告:队列为空,没有什么可创建的。") + print("-" * 30) + continue + + print(f"\n开始执行批量创建,共 {len(path_queue)} 个任务...") + success_count = 0 + created_paths = [] + + for p_str in path_queue: + target_path = pathlib.Path(p_str) + try: + target_path.mkdir(parents=True, exist_ok=True) + print(f" [OK] Created: {target_path}") + success_count += 1 + created_paths.append(str(target_path)) + except Exception as e: + print(f" [ERR] Failed: {target_path} | 原因: {e}") + + print(f"\n执行完毕。成功: {success_count} / 总计: {len(path_queue)}") + + log_index = get_next_log_index() + log_file = pathlib.Path(f"path_list_{log_index}.log") + with log_file.open("w", encoding="utf-8") as f: + for p in created_paths: + f.write(p + "\n") + print(f"已生成日志文件: {log_file}") + + print("-" * 30) + path_queue.clear() + continue + + if raw_path.lower() == ':back': + if path_queue: + confirm = input(f"队列中还有 {len(path_queue)} 个路径未创建,确定要返回吗?(y/n): ") + if confirm.lower() != 'y': + continue + return + + if not raw_path: + continue + + path_queue.append(raw_path) + print(f"已加入队列: '{raw_path}'") + print("-" * 20) + + +def mode_photo(): + print("\n" + "="*60) + print("已进入 PHOTO 模式 - 图片左右镜像工具") + print("功能:批量将文件夹中的所有图片进行左右镜像翻转") + print("支持格式:.jpg, .jpeg, .png, .bmp, .gif, .webp, .tif, .tiff") + print("操作指南:") + print("1. 输入文件夹路径后按回车 -> 加入待处理队列") + print("2. 输入 ':y' 并回车 -> 批量处理队列中所有文件夹的图片") + print("3. 输入 ':back' -> 返回主菜单") + print("="*60 + "\n") + + try: + from PIL import Image + except ImportError: + print("[错误] 未检测到 Pillow 库!") + print("请先安装 Pillow:") + print(" python.exe -m pip install pillow") + print("或者手动下载 pillow 的 .whl 文件后安装") + input("\n按回车返回主菜单...") + return + + folder_queue = [] + supported_extensions = {'.jpg', '.jpeg', '.png', '.bmp', '.gif', '.webp', '.tif', '.tiff'} + + while True: + queue_count = len(folder_queue) + prompt = f"[{queue_count} 个文件夹待处理] >>> 请输入文件夹路径: " + folder_path = input(prompt).strip() + + if folder_path.lower() == ':y': + if not folder_queue: + print("警告:队列为空,没有什么可处理的。") + print("-" * 30) + continue + + print(f"\n开始执行图片镜像处理,共 {len(folder_queue)} 个文件夹...") + + for folder in folder_queue: + print(f"\n处理文件夹: {folder}") + if not os.path.exists(folder): + print(f" [警告] 文件夹不存在,跳过") + continue + + if not os.path.isdir(folder): + print(f" [警告] 路径不是文件夹,跳过") + continue + + image_count = 0 + error_count = 0 + + for filename in os.listdir(folder): + file_path = os.path.join(folder, filename) + + if not os.path.isfile(file_path): + continue + + _, ext = os.path.splitext(filename) + if ext.lower() not in supported_extensions: + continue + + try: + if ext.lower() in ['.tif', '.tiff']: + with open(file_path, 'rb') as f: + img_data = f.read() + + img = Image.open(BytesIO(img_data)) + + flipped_img = img.transpose(Image.FLIP_LEFT_RIGHT) + + output = BytesIO() + flipped_img.save(output, format='TIFF') + + with open(file_path, 'wb') as f: + f.write(output.getvalue()) + else: + img = Image.open(file_path) + flipped_img = img.transpose(Image.FLIP_LEFT_RIGHT) + flipped_img.save(file_path) + + print(f" [OK] {filename}") + image_count += 1 + + except Exception as e: + print(f" [ERR] {filename} | 原因: {e}") + error_count += 1 + + print(f" 文件夹处理完毕。成功: {image_count}, 失败: {error_count}") + + print(f"\n全部执行完毕!共处理 {len(folder_queue)} 个文件夹。") + print("-" * 30) + folder_queue.clear() + continue + + if folder_path.lower() == ':back': + if folder_queue: + confirm = input(f"队列中还有 {len(folder_queue)} 个文件夹未处理,确定要返回吗?(y/n): ") + if confirm.lower() != 'y': + continue + return + + if not folder_path: + continue + + folder_queue.append(folder_path) + print(f"已加入队列: '{folder_path}'") + print("-" * 20) + + +def print_main_menu(): + print("\n" + "="*60) + print(" 集成工具箱 by FlandreScarle7") + print("="*60) + print("可用模式:") + print(" :mode wb - 文件夹批处理工具 (复制、重命名、标记)") + print(" :mode path - 文件夹批量创建工具") + print(" :mode photo - 图片左右镜像工具") + print(" :exit - 退出程序") + print("="*60) + + +def main(): + print_main_menu() + + while True: + command = input("\n>>> 请输入命令: ").strip().lower() + + if command == ":exit": + print("[系统] 程序已退出。") + sys.exit(0) + + elif command == ":mode wb": + mode_wb() + print_main_menu() + + elif command == ":mode path": + mode_path() + print_main_menu() + + elif command == ":mode photo": + mode_photo() + print_main_menu() + + elif command == ":help": + print_main_menu() + + else: + print("[错误] 未知命令。请输入 :mode wb / :mode path / :mode photo / :exit") + + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + print("\n\n[系统] 程序被强制中断。") + sys.exit(0)