Python文件管理 | 给自己写一个备份文件的程序吧2.0
程序员文章站
2022-06-29 13:29:15
...
上次写过一个备份小程序,但这几次用下来发现会出一些问题
上次写的备份程序是在将办公文件夹中的各文件夹压缩成压缩包,再移动到U盘中。但是每次将压缩包移到U盘中后,总会有一些压缩包是损坏的,不管是用程序压缩的还是手动压缩的都会出这个问题,上网找了很久也没能解答。
于是我索性就改了备份方式,既然压缩不行,我复制粘贴难不成还不行吗?于是就有了今天的小程序
需求分析:我们想要我们的U盘和我们的办公文件夹同步。
具体来说就是:如果我们近期有修改过一些文件,而且U盘中也有这些文件的话,就需要在U盘中更新这些文件;如果我们近期有创建过一些文件,而且U盘中没有这个文件的话,就需要在U盘中创建这些文件;如果我们近期有删除过一些文件,而且U盘中还保留着这些文件,就需要从U盘中删除这些文件
不多bb,直接上代码!(注意,以下代码涉及到文件操作,复制后不要直接运行,否则后果自负!!)
import os, shutil, time
# 获取文件相对路径和修改日期的对应表
def getFileMap(route):
fileMap = dict()
for dirpath, dirnames, filenames in os.walk(route):
for file in os.scandir(dirpath):
# 为了之后比较源目录和目标目录的文件相对路径是否相等,所以转成相对路径
# 同时也规范路径,将所有反斜杠都转成斜杠
relativeFilePath = file.path.replace(route, ".").replace("\\",'/')
# 如果是文件夹对应值就为0,如果是文件对应值就为修改日期时间戳
# 把文件夹也算进去是考虑到有空文件夹也需要备份
if file.is_dir():
fileMap[relativeFilePath] = 0
else:
fileMap[relativeFilePath] = file.stat().st_mtime
return fileMap
# 获取需要备份的文件列表以及失效的文件列表
def getbackupFileMap(originalFileMap, targetFileMap):
backupFileMap = dict()
disabledFileMap = targetFileMap.copy() # 用于存放失效文件和文件夹
# 重要!!!一定要.copy(),不能直接赋值
# 否则两个引用指向同一个对象,后面pop会有问题
for originalFile in originalFileMap: # 对于每一个originalFile
for targetFile in targetFileMap: # 遍历所有的targetFile
# 如果出现相同文件,说明之前创建过这个文件,因此不算在失效文件中,是否需要备份要看修改时间
if originalFile == targetFile:
disabledFileMap.pop(originalFile) # 将其从失效文件列表中除名
# 如果originalFile的修改日期晚于targetFile,说明被改了,需要备份
# 由于文件夹对应值都是0,所以这里加等号默认都要备份
if originalFileMap[originalFile] >= targetFileMap[targetFile]:
backupFileMap[originalFile] = originalFileMap[originalFile]
break # 只要进了originalFile == targetFile就不是新文件了
else: # 如果遍历完了还找不到,说明之前没创建过这个文件,那就需要备份
backupFileMap[originalFile] = originalFileMap[originalFile]
return backupFileMap, disabledFileMap
# 时间戳转换为字符串时间
def changeTimeFormat(time_stamp):
time_struct = time.localtime(time_stamp)
time_str = time.strftime('%Y-%m-%d %H:%M:%S', time_struct)
return time_str
# 备份文件
def backupFile(backupFileMap, originalRoute, targetRoute):
for file in backupFileMap:
originalPath = os.path.join(originalRoute, file.replace("./", ""))
targetPath = os.path.join(targetRoute, file.replace("./", ""))
# 如果是文件,那么file的对应值应该是修改日期的时间戳,可以通过if
if backupFileMap[file]:
print(f"正在备份:{originalPath} {changeTimeFormat(backupFileMap[file])}")
if not os.path.exists(os.path.dirname(targetPath)):
os.mkdir(os.path.dirname(targetPath))
shutil.copy(file, targetPath)
else:
if not os.path.exists(targetPath):
os.mkdir(targetPath)
# 删除无效文件
def removeDisabledFile(disabledFileMap, targetRoute):
for file in disabledFileMap:
targetPath = os.path.join(targetRoute, file.replace("./", ""))
os.remove(targetPath)
print(f"已删除{targetPath}")
if __name__ == "__main__":
start = time.perf_counter()
originalRoute = r'D:\DiamondFile'
targetRoute = r'E:\DiamondFile' # 如果U盘地址有更改要注意
originalFileMap = getFileMap(originalRoute)
targetFileMap = getFileMap(targetRoute)
backupFileMap, disabledFileMap = getbackupFileMap(originalFileMap, targetFileMap)
backupFile(backupFileMap, originalRoute, targetRoute)
print("备份完成,共耗时{:2f}s".format(time.perf_counter() - start))
print("正在删除无效文件")
removeDisabledFile(disabledFileMap, targetRoute)
input()