按照数据搜索整理文件.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. import os
  2. import sys
  3. import shutil
  4. import threading
  5. from pathlib import Path
  6. from tkinter import *
  7. from tkinter import ttk, filedialog, messagebox, scrolledtext
  8. class FileSearchCopyApp:
  9. def __init__(self, root):
  10. self.root = root
  11. self.root.title("文件搜索复制工具")
  12. self.root.geometry("900x700")
  13. # 设置样式
  14. style = ttk.Style()
  15. style.theme_use('clam')
  16. # 主框架
  17. main_frame = ttk.Frame(root, padding="10")
  18. main_frame.grid(row=0, column=0, sticky=(W, E, N, S))
  19. # 搜索目录选择
  20. ttk.Label(main_frame, text="搜索目录:").grid(row=0, column=0, sticky=W, pady=5)
  21. self.search_dir = StringVar()
  22. ttk.Entry(main_frame, textvariable=self.search_dir, width=70).grid(row=0, column=1, padx=5, pady=5)
  23. ttk.Button(main_frame, text="浏览", command=self.select_search_dir).grid(row=0, column=2, padx=5, pady=5)
  24. # 输出目录选择
  25. ttk.Label(main_frame, text="输出目录:").grid(row=1, column=0, sticky=W, pady=5)
  26. self.output_dir = StringVar()
  27. ttk.Entry(main_frame, textvariable=self.output_dir, width=70).grid(row=1, column=1, padx=5, pady=5)
  28. ttk.Button(main_frame, text="浏览", command=self.select_output_dir).grid(row=1, column=2, padx=5, pady=5)
  29. # 数据输入区域
  30. ttk.Label(main_frame, text="数据输入(每行一条记录,格式见示例):").grid(row=2, column=0, columnspan=3, sticky=W, pady=5)
  31. self.text_area = scrolledtext.ScrolledText(main_frame, height=15, width=100)
  32. self.text_area.grid(row=3, column=0, columnspan=3, pady=5)
  33. # 添加示例数据按钮
  34. ttk.Button(main_frame, text="加载示例数据", command=self.load_example).grid(row=4, column=0, sticky=W, pady=5)
  35. # 启动按钮
  36. self.start_button = ttk.Button(main_frame, text="启动搜索复制", command=self.start_process, width=20)
  37. self.start_button.grid(row=4, column=1, pady=10)
  38. # 进度条
  39. self.progress = ttk.Progressbar(main_frame, mode='indeterminate')
  40. self.progress.grid(row=5, column=0, columnspan=3, sticky=(W, E), pady=5)
  41. # 日志输出区域
  42. ttk.Label(main_frame, text="运行日志:").grid(row=6, column=0, columnspan=3, sticky=W, pady=5)
  43. self.log_area = scrolledtext.ScrolledText(main_frame, height=15, width=100, fg='blue')
  44. self.log_area.grid(row=7, column=0, columnspan=3, pady=5)
  45. # 配置网格权重
  46. root.columnconfigure(0, weight=1)
  47. root.rowconfigure(0, weight=1)
  48. main_frame.columnconfigure(1, weight=1)
  49. main_frame.rowconfigure(3, weight=1)
  50. main_frame.rowconfigure(7, weight=1)
  51. def select_search_dir(self):
  52. directory = filedialog.askdirectory()
  53. if directory:
  54. self.search_dir.set(directory)
  55. def select_output_dir(self):
  56. directory = filedialog.askdirectory()
  57. if directory:
  58. self.output_dir.set(directory)
  59. def load_example(self):
  60. example_data = """POCY2605240030791S01,POCY2605240060314S01 JIT SC202605250059 1 待送仓 代发临时仓 抖音-淘米 2026-05-25 18:00:00 顺丰大网 LOG20260525039490 6 SF5196563054023 2026-05-25 15:47:39 2026-05-25 08:15:39 LOGSUB20260525028998 S花都仓[#]广州花都京东4号仓1楼 平台物流 2 2 2604233548[双面绒毛巾+圆网袋](1);2605253660[双面绒浴巾80*130cm+圆形网兜](1);
  61. POCY2605250123665S01,POCY2605250122709S01,POCY2605250123515S01,POCY2605250131779S01,POCY2605250138595S01 JIT SC202605250056 1 待送仓 极点纺织 抖音-淘米 2026-05-25 19:00:00 顺丰大网 LOG20260525032407 6 SF5196563053417 2026-05-25 14:46:29 2026-05-26 13:04:56 LOGSUB20260525024113 S花都仓[#]广州花都京东4号仓1楼 平台物流 6 5 2503131272[70*140深浅条纹浴巾5条装](2);2505241490[6件套(2细浴+1深浅浴+2细毛+1深浅毛)](1);2505241491[6件套(1细浴+2深浅浴+2细毛+1深浅毛)](1);2503131275[70*140深浅条纹浴巾5条装](1);2503131273[70*140深浅条纹浴巾5条装](1);
  62. POCY2605250139110S01 JIT SC202605250046 1 待送仓 代发临时仓 抖音-沐居 2026-05-25 19:00:00 跨越速运 LOG20260525027759 6 KYE500152552118-1-1- 2026-05-25 14:18:44 2026-05-26 13:13:44 LOGSUB20260525020896 S花都仓[#]广州花都京东4号仓1楼 平台物流 1 1 2604153514[树叶擦手巾2条装](1);
  63. POCY2605250121485S01,POCY2605250129690S01,POCY2605250119171S01,POCY2605250121966S01,POCY2605250131590S01,POCY2605250139769S01,POCY2605250139364S01,POCY2605250136957S01,POCY2605250012046S01 JIT SC202605250045 1 待送仓 晋州工厂 抖音-沐居 2026-05-25 19:00:00 跨越速运 LOG20260525027747 6 KYE500152532118-1-1- 2026-05-25 14:18:44 2026-05-26 08:06:03 LOGSUB20260525020890 S花都仓[#]广州花都京东4号仓1楼 平台物流 11 9 240925439[印花宠物毛巾4条装](1);2508151793[男士大尺寸浴裙 麦穗款](1);241022640[豁口毛巾2条装](2);2605073595[35*75cm宠物绣花毛巾 4条装](1);HDJYQ015[蝴蝶结浴裙80*165cm](1);2508151794[男士大尺寸浴裙 欧花款](2);240829219[珊瑚绒印花小毛巾](1);DCBLGGFM04[单层菠萝格干发帽 小熊扣](1);2603213399[雪尼尔鞋套2条装](1);
  64. POCY2605250105996S01 SC202605250044 1 待送仓 晋州工厂 抖音-沐居 2026-05-25 19:00:00 跨越速运 LOG20260525027739 6 KYE500152041019-1-1- 2026-05-25 14:18:44 2026-05-28 00:00:00 LOGSUB20260525020886 S花都仓[#]广州花都京东4号仓1楼 平台物流 24 1 2505301510[60*90小辫子擦车巾600gsm单层](24);"""
  65. self.text_area.delete(1.0, END)
  66. self.text_area.insert(1.0, example_data)
  67. def log_message(self, message, is_error=False):
  68. """在日志区域显示消息"""
  69. self.log_area.insert(END, f"{message}\n")
  70. self.log_area.see(END)
  71. if is_error:
  72. # 可以添加错误计数或其他处理
  73. pass
  74. def search_files(self, search_dir, order_number):
  75. """在搜索目录中搜索包含订单号的文件"""
  76. found_files = []
  77. search_path = Path(search_dir)
  78. try:
  79. # 遍历所有文件
  80. for file_path in search_path.rglob('*'):
  81. if file_path.is_file() and order_number in file_path.name:
  82. found_files.append(file_path)
  83. except Exception as e:
  84. self.log_message(f"搜索 {order_number} 时出错: {str(e)}", True)
  85. return found_files
  86. def copy_files(self, files, output_dir, order_number):
  87. """复制文件到目标目录"""
  88. # 创建订单号目录
  89. target_dir = Path(output_dir) / order_number
  90. target_dir.mkdir(parents=True, exist_ok=True)
  91. copied_count = 0
  92. for file_path in files:
  93. try:
  94. # 构建目标文件路径
  95. target_file = target_dir / file_path.name
  96. # 如果文件已存在,添加序号
  97. if target_file.exists():
  98. base_name = file_path.stem
  99. extension = file_path.suffix
  100. counter = 1
  101. while target_file.exists():
  102. new_name = f"{base_name}_{counter}{extension}"
  103. target_file = target_dir / new_name
  104. counter += 1
  105. # 复制文件
  106. shutil.copy2(file_path, target_file)
  107. copied_count += 1
  108. self.log_message(f" 已复制: {file_path.name} -> {target_file}")
  109. except Exception as e:
  110. self.log_message(f" 复制失败 {file_path.name}: {str(e)}", True)
  111. return copied_count
  112. def process_data(self):
  113. """处理数据的主函数"""
  114. search_dir = self.search_dir.get()
  115. output_dir = self.output_dir.get()
  116. data_text = self.text_area.get(1.0, END).strip()
  117. # 验证输入
  118. if not search_dir:
  119. self.log_message("错误:请选择搜索目录!", True)
  120. return False
  121. if not output_dir:
  122. self.log_message("错误:请选择输出目录!", True)
  123. return False
  124. if not data_text:
  125. self.log_message("错误:请在数据输入框中输入数据!", True)
  126. return False
  127. if not os.path.exists(search_dir):
  128. self.log_message(f"错误:搜索目录不存在! {search_dir}", True)
  129. return False
  130. if not os.path.exists(output_dir):
  131. self.log_message(f"错误:输出目录不存在! {output_dir}", True)
  132. return False
  133. # 解析数据,提取订单号
  134. lines = data_text.split('\n')
  135. order_numbers = set() # 使用set去重
  136. for line_num, line in enumerate(lines, 1):
  137. if not line.strip():
  138. continue
  139. # 按制表符分割
  140. parts = line.split('\t')
  141. if len(parts) >= 3:
  142. order_number = parts[2].strip()
  143. if order_number:
  144. order_numbers.add(order_number)
  145. self.log_message(f"提取订单号: {order_number}")
  146. else:
  147. self.log_message(f"警告:第{line_num}行订单号为空")
  148. else:
  149. self.log_message(f"警告:第{line_num}行格式不正确,字段数不足3个")
  150. if not order_numbers:
  151. self.log_message("错误:未能提取到有效的订单号!", True)
  152. return False
  153. self.log_message(f"\n共提取到 {len(order_numbers)} 个订单号")
  154. self.log_message("=" * 60)
  155. # 处理每个订单号
  156. total_files_copied = 0
  157. processed_orders = 0
  158. for order_number in order_numbers:
  159. self.log_message(f"\n处理订单号: {order_number}")
  160. self.log_message(f"搜索目录: {search_dir}")
  161. # 搜索文件
  162. found_files = self.search_files(search_dir, order_number)
  163. if found_files:
  164. self.log_message(f"找到 {len(found_files)} 个相关文件:")
  165. for file_path in found_files:
  166. self.log_message(f" - {file_path.relative_to(search_dir)}")
  167. # 复制文件
  168. copied_count = self.copy_files(found_files, output_dir, order_number)
  169. total_files_copied += copied_count
  170. self.log_message(f"成功复制 {copied_count} 个文件到 {output_dir}/{order_number}")
  171. processed_orders += 1
  172. else:
  173. self.log_message(f"警告:未找到包含 {order_number} 的文件", True)
  174. self.log_message("\n" + "=" * 60)
  175. self.log_message(f"处理完成!")
  176. self.log_message(f"成功处理订单数: {processed_orders}/{len(order_numbers)}")
  177. self.log_message(f"共复制文件数: {total_files_copied}")
  178. return True
  179. def run_in_thread(self):
  180. """在新线程中运行处理程序"""
  181. self.start_button.config(state=DISABLED)
  182. self.progress.start()
  183. try:
  184. success = self.process_data()
  185. if success:
  186. messagebox.showinfo("完成", "文件搜索复制完成!")
  187. else:
  188. messagebox.showerror("错误", "处理过程中出现错误,请查看日志。")
  189. except Exception as e:
  190. self.log_message(f"程序运行错误: {str(e)}", True)
  191. messagebox.showerror("错误", f"程序运行错误: {str(e)}")
  192. finally:
  193. self.progress.stop()
  194. self.start_button.config(state=NORMAL)
  195. def start_process(self):
  196. """启动处理程序"""
  197. # 在新线程中运行,避免界面卡顿
  198. thread = threading.Thread(target=self.run_in_thread)
  199. thread.daemon = True
  200. thread.start()
  201. def main():
  202. root = Tk()
  203. app = FileSearchCopyApp(root)
  204. root.mainloop()
  205. if __name__ == "__main__":
  206. main()