Python+PyQt5實現(xiàn)文件夾結(jié)構(gòu)映射工具
概述
在日常工作中,我們經(jīng)常需要對文件夾結(jié)構(gòu)進(jìn)行復(fù)制和備份,比如僅復(fù)制一級目錄,或者完整復(fù)制多級目錄,有時還希望連同文件名及后綴創(chuàng)建空文件。手動操作既費(fèi)時又容易出錯。為了解決這個問題,本文將帶來一款基于PyQt5開發(fā)的「文件夾結(jié)構(gòu)映射工具」,支持拖拽選取路徑,三種復(fù)制模式,操作簡單直觀,極大提升工作效率。
本工具代碼精煉,功能實用,界面美觀,適合文件管理、項目結(jié)構(gòu)遷移、代碼備份等多種場景使用。文章將深入解析程序設(shè)計思路、界面布局、功能實現(xiàn),并附上完整源碼下載,方便讀者學(xué)習(xí)和二次開發(fā)。
功能亮點(diǎn)
路徑拖拽與瀏覽雙重選擇:支持從資源管理器拖拽文件夾路徑到輸入框,也可以點(diǎn)擊“瀏覽”按鈕選擇目錄,操作靈活便捷。
多復(fù)制模式支持:
- 僅復(fù)制一級目錄結(jié)構(gòu)(不進(jìn)入子文件夾)
- 復(fù)制多級目錄結(jié)構(gòu)(僅文件夾,無文件)
- 復(fù)制多級目錄結(jié)構(gòu)并創(chuàng)建空文件(文件名與后綴保持一致)
路徑有效性校驗:自動檢測源路徑和目標(biāo)路徑是否合理,防止錯誤操作。
界面簡潔美觀:采用淡雅配色和流暢交互,按鈕及控件布局合理,使用體驗良好。
詳細(xì)提示反饋:復(fù)制完成后彈窗顯示創(chuàng)建文件夾數(shù),異常情況及時警告。
展示效果


- 左側(cè)文本框支持拖拽粘貼目錄路徑
- 右側(cè)按鈕可彈出系統(tǒng)文件夾選擇窗口
- 中間清晰顯示復(fù)制模式單選選項
- 右下角“開始映射結(jié)構(gòu)”按鈕啟動復(fù)制
- 復(fù)制完成彈窗告知成功與否
軟件使用步驟
1.選擇源路徑
可直接拖拽文件夾至左側(cè)輸入框,或點(diǎn)擊“瀏覽”按鈕彈出選擇窗口,選擇想復(fù)制的文件夾。
2.選擇目標(biāo)路徑
同樣支持拖拽或瀏覽選擇,指定復(fù)制結(jié)果保存位置。注意目標(biāo)路徑不能是源路徑的子目錄。
3.選擇復(fù)制模式
- 僅復(fù)制一級目錄
- 復(fù)制多級目錄結(jié)構(gòu),不含文件
- 復(fù)制多級目錄結(jié)構(gòu)并創(chuàng)建空文件
- 根據(jù)需求選擇。
4.點(diǎn)擊“開始映射結(jié)構(gòu)”
程序?qū)催x定模式復(fù)制目錄結(jié)構(gòu)。完成后彈窗顯示操作結(jié)果。
5.查看目標(biāo)路徑
目標(biāo)路徑將生成對應(yīng)的目錄結(jié)構(gòu)(及空文件),驗證復(fù)制是否正確。
代碼解析
1. 主窗口設(shè)計(FolderCopyApp)
繼承自QWidget,設(shè)置窗口標(biāo)題、尺寸和基礎(chǔ)樣式,調(diào)用init_ui()方法構(gòu)建界面。
self.setWindowTitle("?? 文件夾結(jié)構(gòu)映射工具")
self.setGeometry(300, 300, 600, 350)
self.setStyleSheet("""
background-color: #f4f6f9;
font-family: "Segoe UI";
font-size:14px;
""")
2. 拖拽路徑輸入框(DropLineEdit)
繼承自QLineEdit,重寫dragEnterEvent和dropEvent實現(xiàn)路徑拖拽識別,提升用戶體驗。
def dragEnterEvent(self, e):
if e.mimeData().hasUrls():
e.accept()
else:
e.ignore()
def dropEvent(self, e):
if e.mimeData().hasUrls():
path = e.mimeData().urls()[0].toLocalFile()
self.setText(path)
3. 界面布局與控件綁定
使用QVBoxLayout整體垂直布局
每個路徑輸入?yún)^(qū)用QHBoxLayout橫向放置文本框和瀏覽按鈕
復(fù)制模式通過QGroupBox和QRadioButton呈現(xiàn),默認(rèn)選擇一級目錄復(fù)制
“開始映射結(jié)構(gòu)”按鈕綁定復(fù)制功能
self.copy_btn.clicked.connect(self.copy_structure)
4. 復(fù)制結(jié)構(gòu)核心邏輯
copy_structure函數(shù)根據(jù)模式執(zhí)行不同目錄復(fù)制:
一級目錄復(fù)制
or name in os.listdir(source):
full_path = os.path.join(source, name)
if os.path.isdir(full_path):
os.makedirs(os.path.join(target, name), exist_ok=True)
多級目錄復(fù)制
for root, dirs, files in os.walk(source):
rel_path = os.path.relpath(root, source)
target_dir = os.path.join(target, rel_path)
os.makedirs(target_dir, exist_ok=True)
- **多級目錄復(fù)制 + 空文件**
if mode == "with_files":
for file in files:
open(os.path.join(target_dir, file), 'w').close()
5. 異常處理和提示
校驗路徑有效性,防止錯誤操作
捕獲異常,彈窗反饋錯誤
復(fù)制完成后提示創(chuàng)建目錄數(shù)量
源碼下載
import sys
import os
from PyQt5.QtWidgets import (
QApplication, QWidget, QLabel, QLineEdit, QPushButton,
QVBoxLayout, QHBoxLayout, QFileDialog, QRadioButton,
QGroupBox, QMessageBox
)
from PyQt5.QtCore import Qt
class DropLineEdit(QLineEdit):
def __init__(self, *args):
super().__init__(*args)
self.setAcceptDrops(True)
def dragEnterEvent(self, e):
if e.mimeData().hasUrls():
e.accept()
else:
e.ignore()
def dropEvent(self, e):
if e.mimeData().hasUrls():
path = e.mimeData().urls()[0].toLocalFile()
self.setText(path)
class FolderCopyApp(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("?? 文件夾結(jié)構(gòu)映射工具")
self.setGeometry(300, 300, 600, 350)
self.setStyleSheet("""
background-color: #f4f6f9;
font-family: "Segoe UI";
font-size:14px;
""")
self.init_ui()
def init_ui(self):
layout = QVBoxLayout()
# 源路徑
source_layout = QHBoxLayout()
self.source_input = DropLineEdit()
browse_source = QPushButton("瀏覽")
browse_source.setFixedWidth(60)
browse_source.setStyleSheet(self.button_style())
browse_source.clicked.connect(self.select_source)
self.add_field("源路徑(拖拽或選擇)", self.source_input, browse_source, layout, source_layout)
# 目標(biāo)路徑
target_layout = QHBoxLayout()
self.target_input = DropLineEdit()
browse_target = QPushButton("瀏覽")
browse_target.setFixedWidth(60)
browse_target.setStyleSheet(self.button_style())
browse_target.clicked.connect(self.select_target)
self.add_field("目標(biāo)路徑(拖拽或選擇)", self.target_input, browse_target, layout, target_layout)
# 模式選擇
self.mode_group = QGroupBox("選擇復(fù)制模式")
self.mode_group.setStyleSheet("QGroupBox { font-weight: bold; }")
mode_layout = QVBoxLayout()
self.level1_radio = QRadioButton("僅復(fù)制一級目錄結(jié)構(gòu)")
self.multilevel_radio = QRadioButton("復(fù)制多級目錄結(jié)構(gòu)(不含文件)")
self.with_files_radio = QRadioButton("復(fù)制多級結(jié)構(gòu) + 空文件(保留名稱與后綴)")
self.level1_radio.setChecked(True)
mode_layout.addWidget(self.level1_radio)
mode_layout.addWidget(self.multilevel_radio)
mode_layout.addWidget(self.with_files_radio)
self.mode_group.setLayout(mode_layout)
layout.addWidget(self.mode_group)
# 操作按鈕
self.copy_btn = QPushButton("?? 開始映射結(jié)構(gòu)")
self.copy_btn.setStyleSheet(self.button_style())
self.copy_btn.clicked.connect(self.copy_structure)
layout.addWidget(self.copy_btn)
self.setLayout(layout)
def add_field(self, label_text, line_edit, button, layout, sublayout):
label = QLabel(label_text)
label.setStyleSheet("color: #333;")
layout.addWidget(label)
sublayout.addWidget(line_edit)
sublayout.addWidget(button)
layout.addLayout(sublayout)
def button_style(self):
return """
QPushButton {
background-color: #5c9ded;
color: white;
border: none;
padding: 6px 12px;
border-radius: 4px;
font-family: "Segoe UI", "Roboto", "Helvetica Neue", Arial, sans-serif;
font-weight: bold;
}
QPushButton:hover {
background-color: #468be6;
}
"""
def select_source(self):
path = QFileDialog.getExistingDirectory(self, "選擇源目錄")
if path:
self.source_input.setText(path)
def select_target(self):
path = QFileDialog.getExistingDirectory(self, "選擇目標(biāo)目錄")
if path:
self.target_input.setText(path)
def copy_structure(self):
source = self.source_input.text().strip()
target = self.target_input.text().strip()
mode = "level1" if self.level1_radio.isChecked() else \
"multilevel" if self.multilevel_radio.isChecked() else "with_files"
if not source or not target:
QMessageBox.warning(self, "錯誤", "請設(shè)置源路徑和目標(biāo)路徑")
return
if not os.path.exists(source):
QMessageBox.warning(self, "錯誤", "源路徑無效")
return
if os.path.commonpath([source]) == os.path.commonpath([source, target]):
QMessageBox.warning(self, "錯誤", "目標(biāo)路徑不能位于源路徑內(nèi)部")
return
try:
created = 0
if mode == "level1":
# 僅復(fù)制一級目錄結(jié)構(gòu)(直接子文件夾)
for name in os.listdir(source):
full_path = os.path.join(source, name)
if os.path.isdir(full_path):
os.makedirs(os.path.join(target, name), exist_ok=True)
created += 1
else:
for root, dirs, files in os.walk(source):
rel_path = os.path.relpath(root, source)
target_dir = os.path.join(target, rel_path)
os.makedirs(target_dir, exist_ok=True)
created += 1
if mode == "with_files":
for file in files:
try:
open(os.path.join(target_dir, file), 'w').close()
except Exception as fe:
print(f"無法創(chuàng)建文件:{file}, 錯誤:{fe}")
QMessageBox.information(self, "完成", f"結(jié)構(gòu)復(fù)制完成,創(chuàng)建文件夾數(shù):{created}")
except Exception as e:
QMessageBox.critical(self, "錯誤", str(e))
if __name__ == "__main__":
app = QApplication(sys.argv)
window = FolderCopyApp()
window.show()
sys.exit(app.exec_())
總結(jié)
這款基于PyQt5的「文件夾結(jié)構(gòu)映射工具」功能實用,代碼清晰,界面友好,適合所有需要目錄結(jié)構(gòu)復(fù)制的場景。通過拖拽輸入和多復(fù)制模式滿足不同用戶需求。本文不僅介紹了工具功能,還詳細(xì)剖析了關(guān)鍵代碼和實現(xiàn)細(xì)節(jié)。希望對您學(xué)習(xí)PyQt5 GUI開發(fā)、文件系統(tǒng)操作提供有價值的參考。
到此這篇關(guān)于Python+PyQt5實現(xiàn)文件夾結(jié)構(gòu)映射工具的文章就介紹到這了,更多相關(guān)Python文件夾結(jié)構(gòu)映射內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python數(shù)據(jù)分析之聚類分析(cluster analysis)
聚類分析本身不是一個特定的算法,而是要解決的一般任務(wù)。它可以通過各種算法來實現(xiàn),這些算法在理解群集的構(gòu)成以及如何有效地找到它們方面存在顯著差異。這篇文章主要介紹了python數(shù)據(jù)分析之聚類分析(cluster analysis),需要的朋友可以參考下2021-11-11
Python使用Tkinter實現(xiàn)滾動抽獎器效果
Tkinter 是 Python 的標(biāo)準(zhǔn) GUI(Graphical User Interface,圖形用戶接口)庫,Python 使用 Tkinter 可以快速地創(chuàng)建 GUI 應(yīng)用程序。這篇文章主要介紹了Python使用Tkinter實現(xiàn)滾動抽獎器,需要的朋友可以參考下2020-01-01
Python實現(xiàn)tuple和list的轉(zhuǎn)換方式
在Python中,可以使用內(nèi)置的list()和tuple()函數(shù)將tuple和list相互轉(zhuǎn)換,tuple是不可變的,而list是可變的,轉(zhuǎn)換時要注意性能考慮2024-12-12
python自動統(tǒng)計zabbix系統(tǒng)監(jiān)控覆蓋率的示例代碼
這篇文章主要介紹了python自動統(tǒng)計zabbix系統(tǒng)監(jiān)控覆蓋率的示例代碼,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-04-04
Python數(shù)據(jù)結(jié)構(gòu)之順序表的實現(xiàn)代碼示例
這篇文章主要介紹了Python數(shù)據(jù)結(jié)構(gòu)之順序表的實現(xiàn)代碼示例,簡單介紹了順序表的相關(guān)內(nèi)容,然后分享了其代碼示例,具有一定參考價值,需要的朋友可以了解下。2017-11-11

