import os import re import shutil import json # 修复:补充json导入(原代码虽未用,但避免后续扩展报错) import pandas as pd # 修复:补充pandas导入(同理,确保依赖完整) from collections import defaultdict def extract_merge_key(filename): """提取合并键:开头连续数字为键(用于分组),字母开头返回原文件名并标记""" name_without_ext = os.path.splitext(filename)[0] # 匹配开头连续数字(如"123_bolt"→"123","A001"无匹配) num_match = re.match(r'^\d+', name_without_ext) if num_match: return num_match.group(), 'num_start' # 数字开头:返回数字键+类型 else: return name_without_ext, 'letter_start' # 字母开头:返回原名+类型 def merge_obj_by_prefix(input_dir, output_dir): """ 按.obj前缀合并:每组复制排序后第一个文件到输出目录,字母开头文件单独打印 """ # 1. 初始化存储:数字前缀→文件路径列表,字母开头文件列表 num_groups = defaultdict(list) # key: 数字前缀, value: [文件路径1, 文件路径2, ...] letter_files = [] # 存储字母开头的文件名(仅记录,不复制) # 2. 扫描输入目录所有.obj文件(递归包含子目录) print(f"开始扫描 {input_dir} 下的.obj文件...\n") for root, _, files in os.walk(input_dir): for file in files: if file.lower().endswith('.obj'): # 兼容 .OBJ 大写后缀 file_path = os.path.join(root, file) merge_key, start_type = extract_merge_key(file) if start_type == 'num_start': # 数字开头:加入对应分组 num_groups[merge_key].append(file_path) print(f" 数字开头:{file} → 归入组【{merge_key}】") else: # 字母开头:加入未合并列表 letter_files.append(file) print(f" 字母开头:{file} → 不合并(仅记录)") # 3. 检查是否有可处理的文件 if not num_groups and not letter_files: print(f"警告:在 {input_dir} 中未找到任何.obj文件!") return # 4. 创建输出目录(清空原有内容,避免旧文件干扰) if os.path.exists(output_dir): shutil.rmtree(output_dir) # 删除原有目录及文件 os.makedirs(output_dir, exist_ok=True) print(f"\n已创建干净的输出目录:{output_dir}") # 5. 处理每个数字分组:排序后复制第一个文件到输出目录 copied_count = 0 print(f"\n开始处理合并组(共 {len(num_groups)} 组):") for group_key in sorted(num_groups.keys()): # 按数字前缀排序(如123→456) file_paths = num_groups[group_key] # 对组内文件按文件名排序(确保每次复制顺序一致) sorted_files = sorted(file_paths, key=lambda x: os.path.basename(x)) first_file = sorted_files[0] # 取排序后第一个文件 first_filename = os.path.basename(first_file) # 复制文件到输出目录(保留原文件名) dest_path = os.path.join(output_dir, first_filename) shutil.copy2(first_file, dest_path) # copy2 保留文件元信息(修改时间等) copied_count += 1 print(f" 组【{group_key}】:复制排序后第一个文件 → {first_filename}") # 6. 单独打印字母开头的未合并文件 print(f"\n=== 字母开头的未合并零件列表(共 {len(letter_files)} 个)===") if letter_files: for idx, file in enumerate(sorted(letter_files), 1): # 排序后打印,更整齐 print(f" {idx}. {file}") else: print(" 无字母开头的未合并零件") # 7. 输出最终统计 print(f"\n=== 处理完成统计 ===") print(f" 合并组总数:{len(num_groups)} 组") print(f" 成功复制文件数:{copied_count} 个(输出目录:{output_dir})") print(f" 未合并文件数:{len(letter_files)} 个(仅记录,未复制)") if __name__ == "__main__": # -------------------------- # 配置参数(请根据实际情况修改) # -------------------------- INPUT_DIR = "/public/home/wangshuo/gap/assembly/data/part_obj_300" # .obj源文件目录(递归扫描) OUTPUT_DIR = "/public/home/wangshuo/gap/assembly/data/part_obj_300_merge_by_prefix" # 合并后文件输出目录(仅存复制的文件) # 执行合并逻辑 merge_obj_by_prefix(INPUT_DIR, OUTPUT_DIR) print(f"\n✅ .obj零件合并复制完成!输出目录仅保留每组排序后第一个文件。")