Python打造智能批量重命名工具的詳細指南
一、引言
因辦公要求,經(jīng)常需要對眾多、各類文件(夾)進行重命名(如大量原始照片本來是以姓名.jpg形式命名的,但是要求提交的格式是“身份證號碼.jpg”)。人數(shù)少還好說,人數(shù)大就是一個稍微復雜的問題了。當然這個問題也可以通過“暴力”的方式解決(具體怎么“暴力”,我就不多贅述了),但是工作效率會大大折扣。所以,為極大提高辦公效率,就謀生了這個想法。
二、GUI界面設計
使用PyQt5進行界面的搭建,最終界面如下:

1.第一步:確定待命名文件所在的文件夾
直接點擊,即可彈出文件夾選擇對話框。該文件夾存儲的是:所有待命名文件(夾)。即所有待命名文件(架)都應放置在這個文件夾中。


假設有100個文件夾,名稱從1-100,而這100個文件夾被存放在“新建文件夾”中。

第一步選取成功后,會彈出成功的對話框。

2.第二步:下載并填寫對應表文件(.XLSX)
直接點擊即可下載。


該對應表文件(.XLSX)中共有兩列(如下圖),列名分別為“舊文件(夾)名稱(含類型后綴.XXX)”和“新文件(夾)名稱(含類型后綴.XXX)”,兩者分別代表著待命名文件(夾)的現(xiàn)有名稱(即舊名稱)、命名完成后的文件(夾)名稱(即新名稱)。只需將待命名文件(夾)的名稱填寫到第一列,再將其一一對應的新名稱填寫到第二列,保存即可。
說明:如果遇到大量文件(夾)時,暴力方法不能瞬時獲取其文件名稱,即第一列的舊名稱不好填寫時,那么請看這里:一鍵曝光:Python+PyQt實現(xiàn)文件目錄。而有了第一列的數(shù)據(jù)后,第二列在excel中使用最常用的vlookup函數(shù)即可按需求一一匹配搞定。

注意:無論是新名稱還是舊名稱,都需要將其后綴也一一對應填寫在表格中(如下圖)。因為上述的測試舉例對象被隨意選取為文件夾,本身無(.XXX)后綴,所以在表格中直接寫的就是文件名稱(1-100分別對應200-299,上圖只截取了一部分);如果想對圖片(.jpg、.png等類型)、文本文檔.txt、DOC文檔.doc、DOCX文檔.docx、PPT演示文稿.ppt、PPTX演示文稿.pptx、XLS工作表.xls、XLSX工作表.xlsx等多種類型進行重命名(已測試通過,可以實現(xiàn)),則需要把后綴也寫入到單元格中。

當然,如果已經(jīng)之前用過該系統(tǒng)了,跳過此步驟,直接到第三步也可以。
3.第三步:上傳對應表文件(.XLSX)
點擊后,彈出文件選擇對話框。

對文件沒有名稱的限制,只要格式為工作表.xlsx就可以;當然也可以覆蓋重復上傳多次。彈出的文件對話框如下:

同樣,會有上傳成功的提示。

4.第四步:開始批量重命名
直接點擊,即可實現(xiàn)大量對文件(夾)的批量迅速重命名。

當然也會有命名成功的提示。

最終的命名效果如下,可以看到,不費一分力,直接瞬間完成批量重命名。

5.使用提示
當未進行第一步和第三步,直接單擊“開始批量重命名”會有如下提示,請按提示操作即可(當然,若缺少第一步和第三步的任意一步,均會有對應提示;如果已經(jīng)有第二步的對應表文件了,可以直接跳過第二步,且不會報錯)。

如果已經(jīng)完成批量重命名了,但是還持續(xù)點擊“開始批量重命名”,則會有如下提示。

6.界面設計jiemian.py
最后附上通過pyuic5產(chǎn)生的GUI界面代碼jiemian.py:
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'jiemian.ui'
#
# Created by: PyQt5 UI code generator 5.15.11
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.setEnabled(True)
Form.resize(400, 600)
Form.setMinimumSize(QtCore.QSize(400, 600))
Form.setMaximumSize(QtCore.QSize(400, 600))
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap(":/image1.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
Form.setWindowIcon(icon)
self.label = QtWidgets.QLabel(Form)
self.label.setGeometry(QtCore.QRect(60, 250, 201, 21))
font = QtGui.QFont()
font.setFamily("Adobe Arabic")
font.setPointSize(12)
font.setBold(False)
font.setWeight(50)
self.label.setFont(font)
self.label.setObjectName("label")
self.groupBox = QtWidgets.QGroupBox(Form)
self.groupBox.setGeometry(QtCore.QRect(50, 240, 291, 81))
self.groupBox.setAutoFillBackground(False)
self.groupBox.setTitle("")
self.groupBox.setFlat(False)
self.groupBox.setObjectName("groupBox")
self.pushButton_3 = QtWidgets.QPushButton(self.groupBox)
self.pushButton_3.setGeometry(QtCore.QRect(70, 40, 191, 23))
self.pushButton_3.setObjectName("pushButton_3")
self.pushButton_2 = QtWidgets.QPushButton(Form)
self.pushButton_2.setGeometry(QtCore.QRect(50, 540, 291, 31))
self.pushButton_2.setObjectName("pushButton_2")
self.label_5 = QtWidgets.QLabel(Form)
self.label_5.setGeometry(QtCore.QRect(230, 70, 141, 31))
font = QtGui.QFont()
font.setFamily("Adobe Arabic")
font.setPointSize(16)
self.label_5.setFont(font)
self.label_5.setObjectName("label_5")
self.label_8 = QtWidgets.QLabel(Form)
self.label_8.setGeometry(QtCore.QRect(70, 20, 251, 31))
font = QtGui.QFont()
font.setFamily("Adobe Arabic")
font.setPointSize(18)
font.setBold(False)
font.setWeight(50)
self.label_8.setFont(font)
self.label_8.setObjectName("label_8")
self.label_10 = QtWidgets.QLabel(Form)
self.label_10.setGeometry(QtCore.QRect(310, 60, 71, 51))
self.label_10.setText("")
self.label_10.setPixmap(QtGui.QPixmap(":/image1.png"))
self.label_10.setObjectName("label_10")
self.label_2 = QtWidgets.QLabel(Form)
self.label_2.setGeometry(QtCore.QRect(60, 350, 201, 21))
font = QtGui.QFont()
font.setFamily("Adobe Arabic")
font.setPointSize(12)
font.setBold(False)
font.setWeight(50)
self.label_2.setFont(font)
self.label_2.setObjectName("label_2")
self.groupBox_2 = QtWidgets.QGroupBox(Form)
self.groupBox_2.setGeometry(QtCore.QRect(50, 340, 291, 81))
self.groupBox_2.setAutoFillBackground(False)
self.groupBox_2.setTitle("")
self.groupBox_2.setFlat(False)
self.groupBox_2.setObjectName("groupBox_2")
self.pushButton_4 = QtWidgets.QPushButton(self.groupBox_2)
self.pushButton_4.setGeometry(QtCore.QRect(70, 40, 191, 23))
self.pushButton_4.setObjectName("pushButton_4")
self.label_3 = QtWidgets.QLabel(Form)
self.label_3.setGeometry(QtCore.QRect(60, 450, 201, 21))
font = QtGui.QFont()
font.setFamily("Adobe Arabic")
font.setPointSize(12)
font.setBold(False)
font.setWeight(50)
self.label_3.setFont(font)
self.label_3.setObjectName("label_3")
self.groupBox_3 = QtWidgets.QGroupBox(Form)
self.groupBox_3.setGeometry(QtCore.QRect(50, 440, 291, 81))
self.groupBox_3.setAutoFillBackground(False)
self.groupBox_3.setTitle("")
self.groupBox_3.setFlat(False)
self.groupBox_3.setObjectName("groupBox_3")
self.pushButton_5 = QtWidgets.QPushButton(self.groupBox_3)
self.pushButton_5.setGeometry(QtCore.QRect(70, 40, 191, 23))
self.pushButton_5.setObjectName("pushButton_5")
self.groupBox_5 = QtWidgets.QGroupBox(Form)
self.groupBox_5.setGeometry(QtCore.QRect(20, 120, 351, 481))
self.groupBox_5.setTitle("")
self.groupBox_5.setObjectName("groupBox_5")
self.label_7 = QtWidgets.QLabel(Form)
self.label_7.setGeometry(QtCore.QRect(60, 150, 281, 21))
font = QtGui.QFont()
font.setFamily("Adobe Arabic")
font.setPointSize(12)
font.setBold(False)
font.setWeight(50)
self.label_7.setFont(font)
self.label_7.setObjectName("label_7")
self.groupBox_6 = QtWidgets.QGroupBox(Form)
self.groupBox_6.setGeometry(QtCore.QRect(50, 140, 291, 81))
self.groupBox_6.setAutoFillBackground(False)
self.groupBox_6.setTitle("")
self.groupBox_6.setFlat(False)
self.groupBox_6.setObjectName("groupBox_6")
self.pushButton_6 = QtWidgets.QPushButton(self.groupBox_6)
self.pushButton_6.setGeometry(QtCore.QRect(70, 40, 191, 23))
self.pushButton_6.setObjectName("pushButton_6")
self.groupBox_5.raise_()
self.groupBox_2.raise_()
self.groupBox_6.raise_()
self.groupBox_3.raise_()
self.groupBox.raise_()
self.label.raise_()
self.pushButton_2.raise_()
self.label_5.raise_()
self.label_8.raise_()
self.label_10.raise_()
self.label_2.raise_()
self.label_3.raise_()
self.label_7.raise_()
self.retranslateUi(Form)
self.pushButton_2.clicked.connect(Form.close) # type: ignore
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "Batch_rename"))
self.label.setText(_translate("Form", "二、請下載對應表文件:"))
self.pushButton_3.setText(_translate("Form", "點擊下載對應表模板文件"))
self.pushButton_2.setText(_translate("Form", "退出系統(tǒng)"))
self.label_5.setText(_translate("Form", "Designed By"))
self.label_8.setText(_translate("Form", "文件批量重命名系統(tǒng)"))
self.label_2.setText(_translate("Form", "三、請上傳對應表文件:"))
self.pushButton_4.setText(_translate("Form", "點擊上傳對應表模板文件"))
self.label_3.setText(_translate("Form", "四、開始批量重命名:"))
self.pushButton_5.setText(_translate("Form", "開始批量重命名"))
self.label_7.setText(_translate("Form", "一、請選擇待命名文件所在的文件夾:"))
self.pushButton_6.setText(_translate("Form", "點擊選擇待命名文件所在的文件夾"))
import ziyuan_rc
三、主要程序詳解
1.導入所需模塊
import sys,os import openpyxl from jiemian import * from PyQt5.QtWidgets import QApplication, QWidget # 保持窗口大小和qtdesigner中的一致 from PyQt5 import QtCore QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling) from openpyxl import Workbook
不懂為啥需要導入Qtcore的,請看一鍵曝光:Python+PyQt實現(xiàn)的文件目錄。
2.初始化設置
class login_interface(QWidget, Ui_Form):
def __init__(self):
super(QWidget, self).__init__()
self.setupUi(self)
# 綁定信號
self.pushButton_3.clicked.connect(self.xiazai)
self.pushButton_4.clicked.connect(self.shangchuan)
self.pushButton_5.clicked.connect(self.kaishi)
self.pushButton_6.clicked.connect(self.daimingming)
# 設置按鍵標志位
self.duqu_flag = False
self.shangchuan_flag = False
# 初始化定義新、舊名稱列表
self.duqu = []
self.jiumingcheng = []
self.xinmingcheng = []
# 待命名的文件所在文件夾的路徑
self.lujing = ""對一些pushbutton綁定相應信號;duqu_flag和shangchuan_flag是標志位,用于判斷用戶是否完成步驟一和步驟三,以便進行后續(xù)操作;列表duqu用于存放所有待命名文件的名稱(如果有后綴的話則包含后綴);列表jiumingcheng代表對應表文件中的第一列數(shù)據(jù)(除列名以外;如果有后綴的話則包含后綴);列表xinmingcheng代表對應表文件中的第二列數(shù)據(jù)(除列名以外;如果有后綴的話則包含后綴);lujing表示待命名文件(夾)所在文件夾的路徑。
3.確定待命名文件所在的文件夾
def daimingming(self):
# 讀取待命名的所有文件名稱
filepath = QtWidgets.QFileDialog.getExistingDirectory(self, "請選取存放待命名文件的文件夾") # 獲取文件夾的路徑
try:
if filepath:
self.lujing = filepath
self.duqu = os.listdir(filepath)
self.duqu = str_genggai(self.duqu)
self.duqu_flag = True
QtWidgets.QMessageBox.information(self, "成功", "選取存放待命名文件的文件夾成功!")
else:
QtWidgets.QMessageBox.critical(self, "提示", "請選擇合適的文件夾!")
except:
QtWidgets.QMessageBox.critical(self, "提示", "請選擇合適的文件夾!")通過QFileDialog獲取其所在的路徑filepath,并賦值給lujing;使用os.listdir()讀取所有文件(夾)的名稱,為避免后期出現(xiàn)內(nèi)容相符,但因格式不一致而匹配不到的問題(如1與'1'不相等,雖 然都表示數(shù)字1,但前者是int類型,后者是str類型),提前在此通過自定義函數(shù)str_genggai將其強制轉(zhuǎn)換為str類型。
4.設置對應表文件(.XLSX)格式
def xiazai(self):
# 下載對應表模板文件
wb = Workbook()
ws = wb.active
ws.column_dimensions['A'].width = 36
ws.column_dimensions['B'].width = 36
ws.cell(row=1, column=1, value="舊文件(夾)名稱(含類型后綴.XXX)")
ws.cell(row=1, column=2, value="新文件(夾)名稱(含類型后綴.XXX)")
wb.save('duiyingbiao.xlsx')
QtWidgets.QMessageBox.information(self,"成功","對應表模板文件下載成功,請查看!")主要對列寬及列名進行設定。
5.上傳并存儲新、舊名稱
def shangchuan(self):
filepath, _ = QtWidgets.QFileDialog.getOpenFileName(self, "請選擇對應表文件", "", "XLSX工作表 (*.xlsx)") # 獲取文件路徑
try:
if filepath:
wb = openpyxl.load_workbook(filepath) # 根據(jù)獲取到的文件路徑來讀取文件
sheet = wb['Sheet']
# 讀取文件中的新、舊名稱
for row in sheet.iter_rows(min_row=2, max_row=sheet.max_row, min_col=1, max_col=1):
for cell in row:
self.jiumingcheng.append(cell.value)
for row in sheet.iter_rows(min_row=2, max_row=sheet.max_row, min_col=2, max_col=2):
for cell in row:
self.xinmingcheng.append(cell.value)
self.shangchuan_flag = True
self.jiumingcheng = str_genggai(self.jiumingcheng)
self.xinmingcheng = str_genggai(self.xinmingcheng)
QtWidgets.QMessageBox.information(self, "成功", "對應表模板文件上傳成功!")
else:
QtWidgets.QMessageBox.critical(self, "提示", "請選擇XLSX工作表類型!")
except:
QtWidgets.QMessageBox.critical(self, "提示", "請選擇正確的XLSX工作表類型!")將對應表(.XLSX)的第一列內(nèi)容從上至下按序存儲在jiumingcheng中,將對應表(.XLSX)的第二列內(nèi)容從上至下按序存儲在xinmingcheng中。同樣,為避免格式不一致,提前通過自定義函數(shù)str_genggai將其強制轉(zhuǎn)換為str類型。最后,考慮特殊情況(如雖然打開了對話框,但并未上傳對應表(.XLSX)文件等),處理異常。
6.開始批量重命名
def kaishi(self):
# 根據(jù)標志位來判斷按鍵/選擇情況
try:
if self.duqu_flag == True:
if self.shangchuan_flag == True:
rename(self.duqu,self.xinmingcheng,self.jiumingcheng, self.lujing)
QtWidgets.QMessageBox.information(self, "成功", "所有文件命名成功!")
else:
QtWidgets.QMessageBox.critical(self, "提示", "請完成步驟三:上傳對應表文件!")
else:
if self.shangchuan_flag == True:
QtWidgets.QMessageBox.critical(self, "提示", "請完成步驟一:選擇待命名文件所在的文件夾!")
else:
QtWidgets.QMessageBox.critical(self, "提示", "請完成步驟一和步驟三!")
except:
QtWidgets.QMessageBox.critical(self, "提示", "已完成批量命名,請勿重復操作!")以duqu_flag和shangchuan_flag兩個標志位為條件進行判斷,如若都滿足,調(diào)用自定義函數(shù)rename進行批量重命名操作。
7.自定義函數(shù)
def str_genggai(filelist):
# 將列表中的數(shù)據(jù)類型強制轉(zhuǎn)換為str
for i in filelist:
index = filelist.index(i)
filelist[index] = str(i)
return filelistdef rename(liebiao, xin, jiu, filepath):
for oldname in liebiao:
if oldname in jiu:
info_index = jiu.index(oldname)
newname = xin[info_index]
os.rename(filepath+'/'+oldname, filepath+'/'+newname)注意:待命名的文件數(shù)不一定等于轉(zhuǎn)換表里的舊名稱數(shù),所以要進行判斷:只有在jiu里的才進行重命名。
四、總程序代碼
import sys,os
import openpyxl
from jiemian import *
from PyQt5.QtWidgets import QApplication, QWidget
# 保持窗口大小和qtdesigner中的一致
from PyQt5 import QtCore
QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling)
from openpyxl import Workbook
class login_interface(QWidget, Ui_Form):
def __init__(self):
super(QWidget, self).__init__()
self.setupUi(self)
# 綁定信號
self.pushButton_3.clicked.connect(self.xiazai)
self.pushButton_4.clicked.connect(self.shangchuan)
self.pushButton_5.clicked.connect(self.kaishi)
self.pushButton_6.clicked.connect(self.daimingming)
# 設置按鍵標志位
self.duqu_flag = False
self.shangchuan_flag = False
# 初始化定義新、舊名稱列表
self.duqu = []
self.jiumingcheng = []
self.xinmingcheng = []
# 待命名的文件所在文件夾的路徑
self.lujing = ""
def daimingming(self):
# 讀取待命名的所有文件名稱
filepath = QtWidgets.QFileDialog.getExistingDirectory(self, "請選取存放待命名文件的文件夾") # 獲取文件夾的路徑
try:
if filepath:
self.lujing = filepath
self.duqu = os.listdir(filepath)
self.duqu = str_genggai(self.duqu)
self.duqu_flag = True
QtWidgets.QMessageBox.information(self, "成功", "選取存放待命名文件的文件夾成功!")
else:
QtWidgets.QMessageBox.critical(self, "提示", "請選擇合適的文件夾!")
except:
QtWidgets.QMessageBox.critical(self, "提示", "請選擇合適的文件夾!")
def xiazai(self):
# 下載對應表模板文件
wb = Workbook()
ws = wb.active
ws.column_dimensions['A'].width = 36
ws.column_dimensions['B'].width = 36
ws.cell(row=1, column=1, value="舊文件(夾)名稱(含類型后綴.XXX)")
ws.cell(row=1, column=2, value="新文件(夾)名稱(含類型后綴.XXX)")
wb.save('duiyingbiao.xlsx')
QtWidgets.QMessageBox.information(self,"成功","對應表模板文件下載成功,請查看!")
def shangchuan(self):
filepath, _ = QtWidgets.QFileDialog.getOpenFileName(self, "請選擇對應表文件", "", "XLSX工作表 (*.xlsx)") # 獲取文件路徑
try:
if filepath:
wb = openpyxl.load_workbook(filepath) # 根據(jù)獲取到的文件路徑來讀取文件
sheet = wb['Sheet']
# 讀取文件中的新、舊名稱
for row in sheet.iter_rows(min_row=2, max_row=sheet.max_row, min_col=1, max_col=1):
for cell in row:
self.jiumingcheng.append(cell.value)
for row in sheet.iter_rows(min_row=2, max_row=sheet.max_row, min_col=2, max_col=2):
for cell in row:
self.xinmingcheng.append(cell.value)
self.shangchuan_flag = True
self.jiumingcheng = str_genggai(self.jiumingcheng)
self.xinmingcheng = str_genggai(self.xinmingcheng)
QtWidgets.QMessageBox.information(self, "成功", "對應表模板文件上傳成功!")
else:
QtWidgets.QMessageBox.critical(self, "提示", "請選擇XLSX工作表類型!")
except:
QtWidgets.QMessageBox.critical(self, "提示", "請選擇正確的XLSX工作表類型!")
def kaishi(self):
# 根據(jù)標志位來判斷按鍵/選擇情況
try:
if self.duqu_flag == True:
if self.shangchuan_flag == True:
rename(self.duqu,self.xinmingcheng,self.jiumingcheng, self.lujing)
QtWidgets.QMessageBox.information(self, "成功", "所有文件命名成功!")
else:
QtWidgets.QMessageBox.critical(self, "提示", "請完成步驟三:上傳對應表文件!")
else:
if self.shangchuan_flag == True:
QtWidgets.QMessageBox.critical(self, "提示", "請完成步驟一:選擇待命名文件所在的文件夾!")
else:
QtWidgets.QMessageBox.critical(self, "提示", "請完成步驟一和步驟三!")
except:
QtWidgets.QMessageBox.critical(self, "提示", "已完成批量命名,請勿重復操作!")
def str_genggai(filelist):
# 將列表中的數(shù)據(jù)類型強制轉(zhuǎn)換為str
for i in filelist:
index = filelist.index(i)
filelist[index] = str(i)
return filelist
def rename(liebiao, xin, jiu, filepath):
for oldname in liebiao:
# 待命名的文件數(shù)不一定等于轉(zhuǎn)換表里的舊名字數(shù),所以要進行判斷
# 只有在表里的才進行重命名,否則會報錯
if oldname in jiu:
info_index = jiu.index(oldname)
newname = xin[info_index]
os.rename(filepath+'/'+oldname, filepath+'/'+newname)
if __name__ == '__main__':
app = QApplication(sys.argv)
w = login_interface()
w.show()
sys.exit(app.exec_())
以上就是Python打造智能批量重命名工具的詳細指南的詳細內(nèi)容,更多關于Python重命名的資料請關注腳本之家其它相關文章!
相關文章
Python采集數(shù)據(jù)保存CSV文件出現(xiàn)內(nèi)容亂碼的解決方法
這篇文章主要為大家詳細介紹了如何解決Python中保存CSV文件內(nèi)容亂碼的問題,并提供詳細的示例代碼以更好地理解和解決這個問題,希望對大家有所幫助2024-03-03
Python Print實現(xiàn)在輸出中插入變量的例子
今天小編就為大家分享一篇Python Print實現(xiàn)在輸出中插入變量的例子,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-12-12
Python Playwright UI自動化測試環(huán)境配置完全指南
Playwright 是微軟出品的強大跨瀏覽器自動化測試工具,相比 Selenium 具有更快的執(zhí)行速度、更好的穩(wěn)定性、更現(xiàn)代的API設計,本文詳細介紹如何在 Windows 環(huán)境下配置 Playwright 測試環(huán)境,并在 Trae IDE 中進行開發(fā)2026-06-06
Tensorflow使用tfrecord輸入數(shù)據(jù)格式
這篇文章主要介紹了Tensorflow使用tfrecord輸入數(shù)據(jù)格式,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-06-06

