【Python】Python 将一个文件夹备份到一个 ZIP 文件

Python 将一个文件夹备份到一个 ZIP 文件

一、 背景介绍

假定你正在做一个项目,它的文件保存在C::raw-latex:\AlsPythonBook文件夹中。 你担心工作会丢失,所以希望为整个文件夹创建一个ZIP文件,作为“快照”。 你希望保存不同的版本,希望 ZIP文件的文件名每次创建时都有所变化。 例如 AlsPythonBook_1.zip、AlsPythonBook_2.zip 、 AlsPythonBook_3.zip,等等。你可以手工完成,但这有点烦人, 而且可能不小心弄错 ZIP 文件的编号。 运行一个程序来完成这个烦人的任务会简单得多。

针对这个项目,打开一个新的文件编辑器窗口, 将它保存为 backupToZip.py 。

二、操作步骤

1. 第1步:弄清楚 ZIP 文件的名称

这个程序的代码将放在一个名为 backupToZip() 的 函数中。这样就更容易将该函数复制粘贴到其他需要 这个功能的Python程序中。在这个程序的末尾,会调用这个 函数进行备份。让你的程序看起来像这样:

#! python3
#backupToZip.py - Copies an entire folder and its contents into
#a ZIP file whose filename increments.

import zipfile, os

def backupToZip(folder):
# Backup the entire contents of “folder” into a ZIP file.

folder = os.path.abspath(folder) # make sure folder is absolute

# Figure out the filename this code should use based on
# what files already exist.
number = 1
while True:
    zipFilename = os.path.basename(folder) + '_' + str(number) + '.zip'
    if not os.path.exists(zipFilename):
        break
    number = number + 1

# TODO: Create the ZIP file.

# TODO: Walk the entire folder tree and compress the files in each folder.
print('Done.')

backupToZip(‘F:\delicious’)
先完成基本任务:添加 #! 行,描述该程序做什么, 并导入 zipfile 和 os 模块。

定义 backupToZip() 函数,它只接收一个参数, 即 folder 。这个参数是一个字符串路径, 指向需要备份的文件夹。该函数将决定它创建的 ZIP文件使用什么文件名,然后创建该文件, 遍历 folder 文件夹,将每个子文件夹和文件添加到ZIP文件中。 在源代码中为这些步骤写下 TODO 注释,提醒你稍后来完成。

第一部分命名这个ZIP文件,使用folder 的绝对路径的基本名称。 如果要备份的文件夹是 C::raw-latex:delicious , ZIP 文件的名称就应该 是 delicious_N.zip ,第一次运行该程 序时 N = l,第二次运行时 N =2,以此类推。

通过检查 delicious_1.zip 是否存在, 然后检查 delicious_2.zip 是否存在,继续下 去,可以确定 N 应该是什么。用一个名为 number 的变量表示 N, 在一个循环内不断增加它,并调用 os.path.exists() 来 检查该文件是否存在。第一个不存在的文件名将导致循环 break,因此它就发现了新 ZIP 文件的文件名。

2. 第2步:创建新 ZIP 文件

接下来让我们创建 ZIP 文件。让你的程序看起来像这样:

#! python3
#backupToZip.py - Copies an entire folder and its contents into
#a ZIP file whose filename increments.

–snip–
while True:
zipFilename = os.path.basename(folder) + ‘_’ + str(number) + ‘.zip’
if not os.path.exists(zipFilename):
break
number = number + 1

# Create the ZIP file.
print('Creating %s...' % (zipFilename))
backupZip = zipfile.ZipFile(zipFilename, 'w')

# TODO: Walk the entire folder tree and compress the files in each folder.
print('Done.')

backupToZip(‘F:\delicious’)
既然新 ZIP 文件的文件名保存在 zipFilename 变量中, 你就可以调用 zipfile.ZipFile() , 实际创建这个 ZIP 文件 。确保传入 ‘w’ 作为 第二个参数,这样 ZIP 文件以写模式打开。

3. 第3步:遍历目录树并添加到 ZIP 文件

现在需要使用 os.walk() 函数, 列出文件夹以及子文件夹中的每个文件。 让你的程序看起来像这样:

#! python3

backupToZip.py

Copies an entire folder and its contents into

a zip file whose filename increments.

import zipfile, os

folder = os.path.abspath(‘.’) # make sure folder is absolute
注意, 不要将备份的结果文件放到要备份的文件夹中,不然备份程序会循环读取备份的结果文件,导致结果文件无限变大,直至充满硬盘空间。

这里为了方便将文件保存到 /tmp 文件夹中。实际使用要放到恰当的位置。

Figure out the filename this code should used based on

what files already exist.

number = 1
while True:
zipFilename = ‘/tmp/xx_’ + os.path.basename(folder) + ‘_’ + str(number) + ‘.zip’
if not os.path.exists(zipFilename):
break
number = number + 1

Create the zip file.

print(‘Creating %s…’ % (zipFilename))
backupZip = zipfile.ZipFile(zipFilename, ‘w’)

Walk the entire folder tree and compress the files in each folder.

for foldername, subfolders, filenames in os.walk(folder):
print(‘Adding files in %s…’ % (foldername))
# Add the current folder to the ZIP file.
backupZip.write(foldername)

# Add all the files in this folder to the ZIP file.
for filename in filenames:
    if filename.startswith(os.path.basename(folder) + '_') and filename.endswith('.zip'):
        continue # don't backup the backup ZIP files
    backupZip.write(os.path.join(foldername, filename))

backupZip.close()
print(‘Done.’)
Creating /tmp/xx_ch03_file_1.zip…
Adding files in /home/bk/book-jubook/python/jubook_python/pt04_essential/ch03_file…
Adding files in /home/bk/book-jubook/python/jubook_python/pt04_essential/ch03_file/.ipynb_checkpoints…
Done.
可以在 for 循环中使用 os.walk ,在每次迭代中, 它将返回这次迭代当前的文件夹名称、这个文件夹中的子文件夹, 以及这个文件夹中的文件名。

在这个 for 循环中,该文件夹被添加到 ZIP 文件。 嵌套的 for 循环将遍历 filenames 列表中的每个文件。 每个文件都被添加到 ZIP 文件中,以前生成的备份 ZIP 文件除外。

如果运行该程序,它产生的输出看起来像这样:

Creating delicious_1.zip…
Adding files in C:\delicious…
Adding files in C:\delicious\cats…
Adding files in C:\delicious\waffles…
Adding files in C:\delicious\walnut…
Adding files in C:\delicious\walnut\waffles…
Done.
第二次运行它时,它将 C::raw-latex:delidous 中的所有文件放进一个 ZIP 文件, 命名为 delicious_2.zip,以此类推。

4. 第4步:类似程序的想法

你可以在其他程序中遍历一个目录树, 将文件添加到压缩的 ZIP 归档文件中。 例如,你可以编程做下面的事情:

遍历一个目录树,将特定扩展名的文件归档,诸如 .txt 或 .py ,并排除其他文件。

遍历一个目录树,将除 .txt 和 .py 文件以外的其他文件归档。

在一个目录树中查找文件夹,它包含的文件数最多,或者使用的磁盘空间最大。

5. 小结

即使你是一个有经验的计算机用户, 可能也会用鼠标和键盘手工处理文件。 现在的文件浏览器使得处理少量文件的工作很容易。 但有时候,如果用计算机的浏览器, 你需要完成的任务可能要花几个小时。

os 和 shutil 模块提供了一些函数, 用于复制、移动、改名和删除文件。在删除文件时, 你可能希望使用 send2trash 模块, 将文件移动到回收站或垃圾箱, 而不是永久地删除它们。在编程处理文件时, 最好是先注释掉实际会复制/移动/改名/删除 文件的代码,添加 print() 调用, 这样你就可以运行该程序,验证它实际会做什么。

通常,你不仅需要对一个文件夹中的文件执行这些操作, 而是对所有下级子文件夹执行操作。os.walk() 函数 将处理这个艰苦工作,遍历文件夹,这样你就可以专注 于程序需要对其中的文件做什么。

zipfile 模块提供了一种方法,用Python压缩和解压ZIP 归档文件。和 os 和 shutil 模块中的文件处理函数 一起使用,很容易将硬盘上任意位置的一些文件打包。 和许多独立的文件相比,这些 ZIP 文件更容易上传到网站, 或作为 E-mail 附件发送。

本书前面几章提供了源代码让你拷贝。 但如果你编写自己的程序,可能在第一次编写时不会完美无缺。 下一章将聚焦于一些Python模块,它们帮助你分析和调试程序, 这样就能让程序很快正确运行。

6.重点疑问

1.shutil.copy() 和shutil.copytree() 之间的区别是什么?

2.什么函数用于文件改名?

3.send2trash 和 shutil 模块中的删除函数之间的区别是什么?

4.ZipFile 对象有一个 close() 方法,就像 File 对象的 close() 方法。 ZipFile 对象 的什么方法等价于 File 对象的 open() 方法?

你可能感兴趣的:(Python,技术研发,项目管理,python,linux,开发语言)