import gradio as gr import zipfile import py7zr import os import tempfile import shutil from datetime import datetime def process_archives(uploaded_files, position, options, custom_text, pack_mode): if not uploaded_files: return [] processed_files = [] temp_dir = tempfile.mkdtemp() current_time_str = datetime.now().strftime("%Y%m%d_%H%M%S") # 如果是一鍵打包,建立一個共用的資料夾來存放所有重新命名的檔案 if pack_mode == "一鍵打包": master_renamed_dir = os.path.join(temp_dir, "master_renamed") os.makedirs(master_renamed_dir, exist_ok=True) for file_path in uploaded_files: filename = os.path.basename(file_path) ext = os.path.splitext(filename)[1].lower() # 確保是 zip 或 7z 檔 if ext not in ['.zip', '.7z']: continue archive_basename = os.path.splitext(filename)[0] extract_dir = os.path.join(temp_dir, f"extracted_{archive_basename}") os.makedirs(extract_dir, exist_ok=True) # 根據副檔名選擇解壓縮方式 try: if ext == '.zip': with zipfile.ZipFile(file_path, 'r') as zip_ref: zip_ref.extractall(extract_dir) elif ext == '.7z': with py7zr.SevenZipFile(file_path, mode='r') as z_ref: z_ref.extractall(path=extract_dir) except Exception as e: print(f"無法讀取壓縮檔 {filename}: {e}") continue # 決定重新命名後的檔案要放哪裡 if pack_mode == "個別打包": renamed_dir = os.path.join(temp_dir, f"{archive_basename}_renamed") os.makedirs(renamed_dir, exist_ok=True) else: renamed_dir = master_renamed_dir # 組合要增加的文字 components = [] if "壓縮檔名" in options: components.append(archive_basename) if "日期時間" in options: components.append(current_time_str) if "自訂文字" in options and custom_text.strip(): components.append(custom_text.strip()) add_str = "_".join(components) # 重新命名檔案並攤平放到新資料夾 for root, dirs, files in os.walk(extract_dir): for f in files: old_path = os.path.join(root, f) if not add_str: new_filename = f else: if position == "前綴": new_filename = f"{add_str}_{f}" else: name, file_ext = os.path.splitext(f) new_filename = f"{name}_{add_str}{file_ext}" # 防呆機制:避免同名檔案覆蓋 (特別是在一鍵打包時) new_path = os.path.join(renamed_dir, new_filename) if os.path.exists(new_path): name, file_ext = os.path.splitext(new_filename) counter = 1 while os.path.exists(os.path.join(renamed_dir, f"{name}_{counter}{file_ext}")): counter += 1 new_filename = f"{name}_{counter}{file_ext}" new_path = os.path.join(renamed_dir, new_filename) shutil.copy2(old_path, new_path) # 如果是個別打包,處理完一個壓縮檔就立刻打包 if pack_mode == "個別打包": output_archive_name = f"processed_{filename}" output_archive_path = os.path.join(temp_dir, output_archive_name) if ext == '.zip': with zipfile.ZipFile(output_archive_path, 'w', zipfile.ZIP_DEFLATED) as out_zip: for root, dirs, files in os.walk(renamed_dir): for f in files: file_to_zip = os.path.join(root, f) out_zip.write(file_to_zip, arcname=f) elif ext == '.7z': with py7zr.SevenZipFile(output_archive_path, 'w') as out_7z: for root, dirs, files in os.walk(renamed_dir): for f in files: file_to_7z = os.path.join(root, f) out_7z.write(file_to_7z, arcname=f) processed_files.append(output_archive_path) # 如果是一鍵打包,等全部檔案處理完後,統一打包成一個 ZIP if pack_mode == "一鍵打包": output_archive_path = os.path.join(temp_dir, "all_processed_files.zip") with zipfile.ZipFile(output_archive_path, 'w', zipfile.ZIP_DEFLATED) as out_zip: for root, dirs, files in os.walk(master_renamed_dir): for f in files: file_to_zip = os.path.join(root, f) out_zip.write(file_to_zip, arcname=f) processed_files.append(output_archive_path) return processed_files # 建立 Gradio 網頁介面 with gr.Blocks(title="壓縮檔內容批次重新命名工具", theme=gr.themes.Soft()) as demo: gr.Markdown("## 📦 壓縮檔內容批次重新命名工具 (支援 ZIP 與 7Z)") gr.Markdown("上傳 `.zip` 或 `.7z` 檔案後,自訂你想增加的文字與位置,並選擇個別下載或是一鍵打包下載。") with gr.Row(): with gr.Column(scale=1): gr.Markdown("### ⚙️ 命名規則設定") position_radio = gr.Radio( choices=["前綴", "後綴"], value="前綴", label="1. 附加位置", info="前綴:加在檔名最前方 / 後綴:加在副檔名之前" ) options_checkbox = gr.CheckboxGroup( choices=["壓縮檔名", "日期時間", "自訂文字"], value=["壓縮檔名"], label="2. 要增加的內容 (可複選)", info="勾選多項時,會自動以底線「_」連接" ) custom_text_input = gr.Textbox( label="3. 輸入自訂文字", placeholder="例如:v2", info="需在上方勾選「自訂文字」才會生效" ) pack_mode_radio = gr.Radio( choices=["個別打包", "一鍵打包"], value="個別打包", label="4. 打包方式", info="個別打包:維持原本的壓縮檔數量 / 一鍵打包:將所有檔案統合成一個 ZIP 檔" ) with gr.Column(scale=1): gr.Markdown("### 📂 檔案上傳與下載") file_input = gr.File(label="上傳壓縮檔 (可多選 ZIP 或 7Z)", file_count="multiple", type="filepath", file_types=[".zip", ".7z"]) submit_btn = gr.Button("🚀 開始處理", variant="primary") file_output = gr.File(label="下載處理後的新壓縮檔") # 綁定按鈕點擊事件,傳入所有設定值 submit_btn.click( fn=process_archives, inputs=[file_input, position_radio, options_checkbox, custom_text_input, pack_mode_radio], outputs=file_output ) if __name__ == "__main__": demo.launch()