学习目标:掌握批量修改文件名称的程序设计方法。
文件和目录
文件通常存储在计算机的磁盘中,计算机中存储的图片、资料、音视频等都是以文件方 式存储的, 每个文件都有一个名称, 可以根据文件的名称来选择打开或存储到某一文件。当计 算机中的文件很多时, 用户使用起来会非常不方便, 因此会建立文件目录, 目录是一个存储文 件的集合,目录下面又有子目录,形成层级目录。
在计算机上管理文件会用到目录的概念,打开计算机就会看到在计算机磁盘中有许多目 录, 目录下面有文件和子目录。这些目录实际上是对文件进行分类管理。人们可以把一些与工 作相关的文件放到工作目录里, 把一些与私人相关的文件放到私人目录中, 当然还有其他更多 的文件分类管理方式。
在计算机中可以创建新的目录和文件,也可以修改原有目录和文件的名称,还可以删除 文件或目录, 不过删除目录时需要谨慎, 防止误删除重要的文件。对这些目录进行的操作都是 通过程序来完成的,计算机的资源管理器就属于这种程序。
Python 语言也支持对文件和目录进行处理,包括文件的创建、重命名、读取和写入、删 除等操作。通过这些操作可以对文件进行批处理,实现大量文件操作的自动化。
目录路径是指从磁盘盘符到目录所在位置的路径。例如,如果要在 D 盘盘符下创建一个 名称为“document”的目录,则目录路径为“d:\ document ”,其中字母“d”是目录所在的盘
符号,“document ”是目录名称,“\ ”为分隔各级目录的符号, 需要注意的是分隔符号在 Windows 操作系统下是“\”,在 Linux 操作系统下是“/”。
文件路径是指从盘符开始到文件所在存储位置的路径,包括目录路径和文件名称。下面是一个文件路径的示例:
D: \ document \pic\团建活动_20210312_0001.jpg。
拼接文件路径
os.path 模块内的join(path , *paths)函数可以将目录和文件拼接为文件路径,该函数将*paths 表示的路径拼接到path 路径上。
例如:
import os.path
filepath = os.path.join("d:\\document\pic\\","团建活动_20210312_0001.jpg")
提取文件创建时间
os 模块的 stat 函数可以获取文件的属性, 文件的属性也包括文件的创建时间。 stat 函数的 声明如下:
stat(path, *, dir_fd=None, follow_symlinks=True)
参数 path 为文件路径,路径可以是相对路径,也可以是绝对路径。若函数执行成功,函 数返回 stat_result 对象。
stat_result 对象常用属性见表 7- 1。
表 7-1 stat_result 对象常用属性
| 属性名称 | 属性描述 |
| st_size | 文件大小(以字节为单位) |
| st_ctime | 文件的创建时间,以秒为单位 |
| st_atime | 文件最近的访问时间,以秒为单位 |
| st_mtime | 文件最近的修改时间,以秒为单位 |
| stat | 函数返回的 st_ctime 以秒为单位,程序需要将其转换为自定义的时间格式串(如 20210323) |
【例 7-1】 st_ctime 转换为自定义的时间格式
程序清单如下。
# 导入 os 模块
import os
# 导入 time 模块
import time
# 与代码文件在同一目录
filepath = "../data/img/07/IMG_1310.jpg"
# 获取文件的创建时间
ctime = os.stat(filepath).st_ctime
# 返回 ctime 时间的 struct_time 结构对象
ctime = time.localtime(ctime)
# 格式化时间串
stime = "{0}{1:0>2}{2:0>2}"
stime = stime.format(ctime.tm_year,ctime.tm_mon,ctime.tm_mday)
print(stime)
转换代码用到了 time 模块,time 模块提供了时间的访问和转换函数, 函数 localtime([secs]) 返回 secs 的当地时间 struct_time 结构对象。
struct_time 结构是一个 9 元组,结构中的值可以通过索引和属性名称访问。 struct_time 结构见表 7-2。
表 7-2 struct_time 结构
| 索引 | 属性 | 值 |
| 0 | tm_year | 4 位数字,例如 2020 |
| 1 | tm_mon | 1~2 位数字, 1~12 |
| 2 | tm_mday | 1~2 位数字, 1~31 |
| 3 | tm_hour | 1~2 位数字, 0~23 |
| 4 | tm_min | 1~2 位数字, 0~59 |
| 5 | tm_sec | 1~2 位数字, 0~61 |
| 6 | tm_wday | 1 位数字, 0~6,周一为 0 |
| 7 | tm_yday | 1~3 位数字, 1~366 |
| 8 | tm_isdst | 设置夏令时, 1 为夏令时, 0 为正常 |
文件重命名
os 模块的 rename(src,dst)函数重命名文件或目录, src 是需要重命名的目录或文件路径, dst 是重命名后的目录和文件路径。
例如:
import os
filepath = os.rename("d:\\document\pic\\01.png","d:\\document\pic\\r01.png")
提取文件扩展名
os.path 模块的 splitext(path)函数用于分离文件路径和文件的扩展名,它返回一个二元组, 元组的第一个元素是文件路径,元组的第二个元素是文件的扩展名。
例如:
import os
path = "d:\\document\\pic\\01.png"
print(os.path.splitext(path))
判断文件和目录
在遍历目录文件的过程中,需要判断当前路径是文件还是目录,是目录则忽略。 os.path 模块的 isfile(path)函数可以判断 path 是否是文件,是文件则返回 True。
例如:
print(path.isfile("d:\\document\pic\\01.png"))
遍历文件
遍历是指对目录中的所有文件按顺序逐个访问。例如程序要求列出某个目录中所有的文 件名称, 就需要访问这个目录中的所有文件并获取文件的名称, 然后将获取的文件名称输出到 屏幕上。
os 模块的 listdir(path)函数列出指定目录中所有的文件, 也包括子目录。目录由 path 指定, 访问文件顺序为字母顺序。该方法返回列表数据。
【例 7-2】 遍历目录文件
#导入 OS 模块
import os
#待遍历的目录路径
path = "../data"
#调用 listdir 方法遍历path 目录
dirs = os.listdir(path)
# 输出所有文件和文件夹
for file in dirs:
print(file)
文件批量命令示例
【例 7-3】 从手机或数码相机导入计算机的照片,照片文件名称不方便记忆和分类。现 在需要编写一个 Python 程序,对这些照片文件重新命名,命名规则为:
照片标签_创建日期_序号
照片标签指照片的出处、来源;创建日 期指照片的拍摄日期;序号指照片的序号, 为 4 位数字。
例如,团建活动_20210312_0001.jpg。
图 7- 1 展示了照片文件批量命名的处理 流程。
程序清单如下。
'''
案例:照片文件批量命名
'''
# 导入 os 模块
import os
# 导入 time 模块
import time
# 照片标签
v_pic_tag = "团建活动"
# 照片序号
v_pic_no = 1
# 照片目录
v_pic_path = "../data/img/07/"
# 时间转换函数
def f_to_time(t):
# 返回 t 时间的 struct_time 结构对象
ctime = time.localtime(t)
# 格式化时间串
strtime = "{0}{1:0>2}{2:0>2}"
return strtime.format(ctime.tm_year,ctime.tm_mon,ctime.tm_mday)
# 拼接照片文件名称函数
def f_to_filename(name,t):
# 格式时间字符串
strtime = f_to_time(t)
# 格式照片文件序号
strno = "{0:0>4}".format(v_pic_no)
# 获取文件的扩展名
fname,ext = os.path.splitext(name)
return v_pic_tag + "_" + strtime + "_" + strno + ext
# 程序入口
if __name__ == '__main__ ':
#调用 listdir 方法遍历 v_pic_path 目录
dirs = os.listdir(v_pic_path)
# 遍历所有照片文件
for file in dirs:
# 拼接目录和文件名称为文件路径
filepath = os.path.join(v_pic_path,file)
# 目录和文件的判断
if os.path.isfile(filepath):
# 获取文件创建时间
t = os.stat(filepath).st_ctime
# 拼接照片文件名称
newname = f_to_filename(file,t)
# 文件重命名
os.rename(filepath,os.path.join(v_pic_path,newname))
# 照片文件序号递增
v_pic_no = v_pic_no + 1
print("处理完成, %d 个文件被重命名" % (len(dirs)))