import os import zipfile import shutil import tempfile import glob import subprocess from pathlib import Path import threading from concurrent.futures import ThreadPoolExecutor, as_completed import time # 导入可能需要安装的库 import tqdm import patoolib # 全局锁用于线程安全的输出和文件操作 print_lock = threading.Lock() file_operation_lock = threading.Lock() def safe_print(*args, **kwargs): """线程安全的打印函数""" with print_lock: print(*args, **kwargs) def safe_file_operation(operation, *args, **kwargs): """线程安全的文件操作函数""" with file_operation_lock: return operation(*args, **kwargs) def extract_archive(archive_path, extract_dir): """解压缩文件到指定目录""" safe_print("正在解压文件...") if archive_path.lower().endswith('.zip'): # 使用zipfile处理zip文件,可以显示进度条 with zipfile.ZipFile(archive_path, 'r') as zip_ref: total = len(zip_ref.namelist()) for file in tqdm.tqdm(zip_ref.namelist(), total=total, desc="解压进度"): zip_ref.extract(file, extract_dir) else: # 使用patoolib处理其他类型的压缩文件,包括RAR patoolib.extract_archive(archive_path, outdir=extract_dir) safe_print("解压完成") # 如果解压后只有一个文件夹,将其内容移到extract_dir items = os.listdir(extract_dir) if len(items) == 1 and os.path.isdir(os.path.join(extract_dir, items[0])): subfolder = os.path.join(extract_dir, items[0]) # 将子文件夹中的所有内容移到extract_dir for item in os.listdir(subfolder): shutil.move(os.path.join(subfolder, item), extract_dir) # 删除空文件夹 os.rmdir(subfolder) def process_files(directory): """处理目录中的文件:删除.bat文件,重命名.jar文件""" safe_print("正在处理文件...") # 查找所有.bat文件并删除 bat_files = [] for root, _, files in os.walk(directory): for file in files: if file.lower().endswith('.bat'): bat_path = os.path.join(root, file) bat_files.append(bat_path) # 使用线程池并行删除.bat文件 if bat_files: def safe_remove_file(file_path): """安全删除文件""" try: safe_file_operation(os.remove, file_path) return True except Exception as e: safe_print(f"删除文件 {file_path} 时出错: {e}") return False with ThreadPoolExecutor(max_workers=4) as executor: futures = [executor.submit(safe_remove_file, bat_file) for bat_file in bat_files] successful_deletions = 0 for future in tqdm.tqdm(as_completed(futures), total=len(futures), desc="删除.bat文件"): if future.result(): successful_deletions += 1 safe_print(f"成功删除 {successful_deletions}/{len(bat_files)} 个.bat文件") else: safe_print("未找到需要删除的.bat文件") # 查找所有.jar文件 jar_files = [] for root, _, files in os.walk(directory): for file in files: if file.lower().endswith('.jar'): jar_path = os.path.join(root, file) jar_files.append(jar_path) # 处理.jar文件 if jar_files: for jar_file in tqdm.tqdm(jar_files, desc="处理.jar文件"): dir_path = os.path.dirname(jar_file) # 检查是否存在fabric-server-launch.jar和server.jar if os.path.basename(jar_file).lower() == 'fabric-server-launch.jar': server_jar = os.path.join(dir_path, 'server.jar') if os.path.exists(server_jar): # 将server.jar重命名为ser.jar ser_jar = os.path.join(dir_path, 'ser.jar') safe_file_operation(shutil.move, server_jar, ser_jar) # 将fabric-server-launch.jar重命名为server.jar safe_file_operation(shutil.move, jar_file, os.path.join(dir_path, 'server.jar')) # 如果是普通的jar文件且不是server.jar或ser.jar,则重命名为server.jar elif os.path.basename(jar_file).lower() != 'server.jar' and os.path.basename(jar_file).lower() != 'ser.jar': # 检查目录中是否已存在server.jar server_jar = os.path.join(dir_path, 'server.jar') if not os.path.exists(server_jar): safe_file_operation(shutil.move, jar_file, server_jar) else: safe_print("未找到需要处理的.jar文件") def compress_directory(source_dir, output_path): """将目录压缩为zip文件,确保解压后直接是文件而不是文件夹""" safe_print("正在压缩文件...") with zipfile.ZipFile(output_path, 'w', zipfile.ZIP_DEFLATED) as zipf: # 获取要压缩的文件列表 file_paths = [] for root, dirs, files in os.walk(source_dir): for file in files: file_path = os.path.join(root, file) file_paths.append(file_path) # 显示压缩进度 for file in tqdm.tqdm(file_paths, desc="压缩进度"): # 计算相对路径,确保解压后不会有额外的目录层级 # 获取文件相对于source_dir的路径 rel_path = os.path.relpath(file, source_dir) # 如果文件在子文件夹中,我们需要保留子文件夹结构,但去掉最外层文件夹 # 例如,如果文件在 temp_dir/folder1/file.txt,我们希望在zip中存储为 folder1/file.txt # 如果文件在 temp_dir/file.txt,我们希望在zip中存储为 file.txt zipf.write(file, rel_path) def process_single_archive(archive_path, current_dir, index, total): """处理单个压缩文件的函数""" safe_print(f"\n[线程 {threading.current_thread().name}] 处理第 {index+1}/{total} 个压缩文件: {os.path.basename(archive_path)}") try: # 创建临时目录用于解压 with tempfile.TemporaryDirectory() as temp_dir: # 解压文件 try: extract_archive(archive_path, temp_dir) except Exception as e: safe_print(f"解压失败: {e}") return False # 处理文件 process_files(temp_dir) # 确保successzip目录存在 success_dir = os.path.join(current_dir, 'successzip') if not os.path.exists(success_dir): safe_file_operation(os.makedirs, success_dir, exist_ok=True) # 创建新的压缩文件名,使用"cjsyun-"前缀,保存到successzip文件夹 processed_archive = os.path.join(success_dir, f"cjsyun-{os.path.basename(archive_path)}") if processed_archive.lower().endswith('.rar'): processed_archive = processed_archive[:-4] + '.zip' # 将RAR转换为ZIP # 压缩处理后的文件 compress_directory(temp_dir, processed_archive) safe_print(f"[线程 {threading.current_thread().name}] 处理完成: {os.path.basename(processed_archive)}") return True except Exception as e: safe_print(f"处理文件时出错: {e}") return False def main(): # 获取当前目录下的所有压缩文件 current_dir = os.path.dirname(os.path.abspath(__file__)) archives = [] for ext in ['*.zip', '*.rar']: archives.extend(glob.glob(os.path.join(current_dir, ext))) if not archives: safe_print("当前目录下没有找到压缩文件") return safe_print(f"找到 {len(archives)} 个压缩文件") # 确定线程数量,最多使用4个线程,但不超过文件数量 max_workers = min(4, len(archives)) safe_print(f"使用 {max_workers} 个线程并行处理") start_time = time.time() # 使用线程池并行处理压缩文件 with ThreadPoolExecutor(max_workers=max_workers, thread_name_prefix="Archive") as executor: # 提交所有任务 futures = [] for i, archive_path in enumerate(archives): future = executor.submit(process_single_archive, archive_path, current_dir, i, len(archives)) futures.append(future) # 等待所有任务完成并收集结果 successful = 0 failed = 0 for future in as_completed(futures): try: result = future.result() if result: successful += 1 else: failed += 1 except Exception as e: safe_print(f"任务执行出错: {e}") failed += 1 end_time = time.time() total_time = end_time - start_time safe_print(f"\n处理完成!") safe_print(f"成功处理: {successful} 个文件") safe_print(f"处理失败: {failed} 个文件") safe_print(f"总耗时: {total_time:.2f} 秒") safe_print(f"平均每个文件: {total_time/len(archives):.2f} 秒") if __name__ == "__main__": main()