File size: 7,308 Bytes
b5c0e56
 
30548fc
b5c0e56
 
 
1de245d
b5c0e56
bcbb7d9
b5c0e56
 
 
 
 
1de245d
 
b5c0e56
bcbb7d9
 
 
 
 
b5c0e56
 
30548fc
b5c0e56
30548fc
 
b5c0e56
 
30548fc
bcbb7d9
b5c0e56
 
30548fc
b5c0e56
30548fc
 
 
 
 
 
 
 
b5c0e56
 
bcbb7d9
 
 
 
 
 
b5c0e56
30548fc
1de245d
 
30548fc
1de245d
 
 
 
 
 
 
30548fc
b5c0e56
 
 
 
1de245d
 
 
 
 
 
30548fc
 
bcbb7d9
 
b5c0e56
bcbb7d9
 
 
 
 
 
 
 
b5c0e56
 
bcbb7d9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b5c0e56
bcbb7d9
 
 
 
 
 
 
 
30548fc
b5c0e56
 
 
 
1de245d
30548fc
bcbb7d9
b5c0e56
 
1de245d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bcbb7d9
 
 
 
 
 
 
1de245d
 
30548fc
1de245d
 
b5c0e56
bcbb7d9
b5c0e56
30548fc
bcbb7d9
b5c0e56
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
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()