欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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()
相关标签: Python文件管理