也许你曾经经历过查找一个文件夹,里面有几十个、几百个,甚至上千个文件,需要手工进行复制、改名、移动或压缩。或者考虑下面这样的任务:
- 在一个文件夹及其所有子文件夹中,复制所有的 pdf 文件(且只复制 pdf 文件)
- 针对一个文件夹中的所有文件,删除文件名中前导的零,该文件夹中有数百个文件,名为 spam001.txt、 spam002.txt、 spam003.txt 等。
- 将几个文件夹的内容压缩到一个 ZIP 文件中(这可能是一个简单的备份系统)所有这种无聊的任务,正是在请求用 Python 实现自动化。通过对电脑编程来完成这些任务,你就把它变成了一个快速工作的文件职员,而且从不犯错。
文章目录
shutil 模块
shutil(或称为 shell 工具)模块中包含一些函数,让你在 Python 程序中复制、移动、改名和删除文件。要使用 shutil 的函数,首先需要 import shutil。
复制文件和文件夹
shutil 模块
提供了一些函数,用于复制文件和整个文件夹。
调用 shutil.copy(source, destination)
,将路径 source 处的文件复制到路径 destination处的文件夹(source 和 destination 都是字符串)。如果 destination 是一个文件名,它将作为被复制文件的新名字。该函数返回一个字符串,表示被复制文件的路径。
>>> import shutil, os
>>> os.chdir('C:\\')
>>> shutil.copy('C:\\spam.txt', 'C:\\delicious')
'C:\\delicious\\spam.txt'
>>> shutil.copy('eggs.txt', 'C:\\delicious\\eggs2.txt')
'C:\\delicious\\eggs2.txt'
第一个 shutil.copy()
调用将文件 C:\spam.txt 复制到文件夹 C:\delicious。返回值是刚刚被复制的文件的路径。请注意,因为指定了一个文件夹作为目的地,原来的文件名 spam.txt 就被用作新复制的文件名。第二个 shutil.copy()调用也将文件C:\eggs.txt 复制到文件夹 C:\delicious,但为新文件提供了一个名字 eggs2.txt.
shutil.copy()将复制一个文件, shutil.copytree()
将复制整个文件夹,以及它包含的文件夹和文件。调用 shutil.copytree(source, destination)
,将路径 source 处的文件夹,包括它的所有文件和子文件夹,复制到路径 destination 处的文件夹。 source 和destination 参数都是字符串。该函数返回一个字符串,是新复制的文件夹的路径。
>>> import shutil, os
>>> os.chdir('C:\\')
>>> shutil.copytree('C:\\bacon', 'C:\\bacon_backup')
'C:\\bacon_backup'
shutil.copytree()调用创建了一个新文件夹, 名为 bacon_backup,其中的内容与原来的 bacon 文件夹一样。现在你已经备份了非常非常宝贵的“bacon”
文件和文件夹的移动与改名
调用 shutil.move(source, destination)
, 将路径 source 处的文件夹移动到路径destination,并返回新位置的绝对路径的字符串。
如果 destination 指向一个文件夹, source 文件将移动到 destination 中, 并保持原来的文件名。
>>> import shutil
>>> shutil.move('C:\\bacon.txt', 'C:\\eggs')
'C:\\eggs\\bacon.txt'
假定在 C:\目录中已存在一个名为 eggs 的文件夹, 这个 shutil.move()调用就是说,“将 C:\bacon.txt 移动到文件夹 C:\eggs 中。
如果在 C:\eggs 中原来已经存在一个文件 bacon.txt,它就会被覆写。因为用这种方式很容易不小心覆写文件, 所以在使用 move()时应该注意。
destination 路径也可以指定一个文件名。在下面的例子中, source 文件被移动并改名。
>>> shutil.move('C:\\bacon.txt', 'C:\\eggs\\new_bacon.txt')
'C:\\eggs\\new_bacon.txt'
这一行是说,“将 C:\bacon.txt 移动到文件夹 C:\eggs,完成之后,将 bacon.txt文件改名为 new_bacon.txt。”
永久删除文件和文件夹
利用 os 模块中的函数,可以删除一个文件或一个空文件夹。但利用 shutil 模块
,可以删除一个文件夹及其所有的内容。
- 用
os.unlink(path)
将删除 path 处的文件。 - 调用
os.rmdir(path)
将删除 path 处的文件夹。该文件夹必须为空,其中没有任何文件和文件夹。 - 调用
shutil.rmtree(path)
将删除 path 处的文件夹,它包含的所有文件和文件夹都会被删除。
import os
for filename in os.listdir():
if filename.endswith('.rxt'):
os.unlink(filename)
遍历目录树
假定你希望对某个文件夹中的所有文件改名, 包括该文件夹中所有子文件夹中的所有文件。也就是说, 你希望遍历目录树, 处理遇到的每个文件。写程序完成这件事,可能需要一些技巧。 好在, Python 提供了一个函数, 替你处理这个过程。
import os
for folderName, subfolders, filenames in os.walk('C:\\delicious'):
print('The current folder is ' + folderName)
for subfolder in subfolders:
print('SUBFOLDER OF ' + folderName + ': ' + subfolder)
for filename in filenames:
print('FILE INSIDE ' + folderName + ': '+ filename)
print('')
os.walk()
函数被传入一个字符串值,即一个文件夹的路径。你可以在一个 for循环语句中使用 os.walk()函数,遍历目录树, 就像使用 range()函数遍历一个范围的数字一样。不像 range(), os.walk()在循环的每次迭代中,返回 3 个值:
- 当前文件夹名称的字符串。
- 当前文件夹中子文件夹的字符串的列表。
- 当前文件夹中文件的字符串的列表。
所谓当前文件夹,是指 for 循环当前迭代的文件夹。程序的当前工作目录,不会因为 os.walk()而改变。
用 zipfile 模块压缩文件
一个 ZIP 文件可以包含多个文件和子文件夹, 所以它是一种很方便的方式, 将多个文件打包成一
个文件。这个文件叫做“归档文件”, 然后可以用作电子邮件的附件,或其他用途。
利用 zipfile 模块中的函数, Python 程序可以创建和打开(或解压) ZIP 文件。假定你有一个名为 example.zip 的 zip 文件, 它的内容如图
读取 ZIP 文件
读取 ZIP 文件的内容, 首先必须创建一个 ZipFile 对象(请注意大写首字母 Z和 F)。 ZipFile 对象在概念上与 File 对象相似,
要创建一个 ZipFile
对象,就调用 zipfile.ZipFile()函数
, 向它传入一个字符串, 表示.zip 文件的文件名。请注意, zipfile 是 Python 模块
的名称,ZipFile()是函数的名称
。
>>> import zipfile, os
>>> os.chdir('C:\\') # move to the folder with example.zip
>>> exampleZip = zipfile.ZipFile('example.zip')
>>> exampleZip.namelist()
['spam.txt', 'cats/', 'cats/catnames.txt', 'cats/zophie.jpg']
>>> spamInfo = exampleZip.getinfo('spam.txt')
>>> spamInfo.file_size
13908
>>> spamInfo.compress_size
3828
>>> 'Compressed file is %sx smaller!' % (round(spamInfo.file_size / spamInfo
.compress_size, 2))
'Compressed file is 3.63x smaller!'
>>> exampleZip.close()
ZipFile 对象有一个 namelist()方法
,返回 ZIP 文件中包含的所有文件和文件夹的字符串的列表。这些字符串可以传递给 ZipFile 对象的 getinfo()方法
,返回一个关于特定文件的 ZipInfo 对象。 ZipInfo 对象有自己的属性,诸如表示字节数的 file_size和 compress_size,它们分别表示原来文件大小和压缩后文件大小。 ZipFile 对象表示整个归档文件,而 ZipInfo 对象则保存该归档文件中每个文件的有用信息。
从 ZIP 文件中解压缩
ZipFile 对象的 extractall()方法从 ZIP 文件中解压缩所有文件和文件夹, 放到当前工作目录中。
>>> import zipfile, os
>>> os.chdir('C:\\') # move to the folder with example.zip
>>> exampleZip = zipfile.ZipFile('example.zip')
>>> exampleZip.extractall()
>>> exampleZip.close()
运行这段代码后, example.zip 的内容将被解压缩到 C:\。或者, 你可以向extractall()传递的一个文件夹名称,它将文件解压缩到那个文件夹, 而不是当前工作目录。如果传递给 extractall()方法的文件夹不存在,它会被创建。
例如, 如果你用exampleZip.extractall(‘C:\ delicious’)取代处的调用, 代码就会从 example.zip 中解压缩文件, 放到新创建的 C:\delicious 文件夹中。
ZipFile 对象的 extract()方法从 ZIP 文件中解压缩单个文件。
>>> exampleZip.extract('spam.txt')
'C:\\spam.txt'
>>> exampleZip.extract('spam.txt', 'C:\\some\\new\\folders')
'C:\\some\\new\\folders\\spam.txt'
>>> exampleZip.close()
传递给 extract()的字符串, 必须匹配 namelist()返回的字符串列表中的一个。或者,你可以向 extract()传递第二个参数, 将文件解压缩到指定的文件夹, 而不是当前工作目录。如果第二个参数指定的文件夹不存在, Python 就会创建它。 extract()的返回值是被压缩后文件的绝对路径。
创建和添加到 ZIP 文件
要创建你自己的压缩 ZIP 文件, 必须以“写模式”打开 ZipFile 对象,即传入’w’作为第二个参数(这类似于向 open()函数传入’w’,以写模式打开一个文本文件)。如果向 ZipFile 对象的 write()方法
传入一个路径, Python 就会压缩该路径所指的文件, 将它加到 ZIP 文件中。 write()方法的第一个参数是一个字符串, 代表要添加的文件名。第二个参数是“压缩类型”参数,它告诉计算机使用怎样的算法来压
缩文件。可以总是将这个值设置为 zipfile.ZIP_DEFLATED( 这指定了 deflate 压缩算法,它对各种类型的数据都很有效)。
>>> import zipfile
>>> newZip = zipfile.ZipFile('new.zip', 'w')
>>> newZip.write('spam.txt', compress_type=zipfile.ZIP_DEFLATED)
>>> newZip.close()
这段代码将创建一个新的 ZIP 文件, 名为 new.zip, 它包含 spam.txt 压缩后的内容。要记住, 就像写入文件一样,写模式将擦除 ZIP 文件中所有原有的内容。如果只是希望将文件添加到原有的 ZIP 文件中, 就要向 zipfile.ZipFile()传入’a’作为第二个参数,以添加模式打开 ZIP 文件。