假如你有成百上千个文件需要处理,复制、改名、移动或压缩,显然人工去做的话,虽然不至于猴年马月,但一定要很久。

常用的场景比如:

• 在一个文件夹及其所有子文件夹中,复制且只复制 pdf 文件到指定文件夹
• 针对一个文件夹中的所有文件,批量高级重命名。
• 将几个文件夹的内容压缩到一个 ZIP 文件中(这可能是一个简单的备份系统)
而所有这种无聊的任务,我们可以用 Python 实现自动化。

Shutil

Python的shutil(或称为 shell 工具)模块中包含一些函数,让你在 Python 程序中复制、移动、改名和删除文件。

我们先导入这个模块,

1
import shutil

复制、移动、改名

shutil.copy(source, destination),将路径 source 处的文件复制到路径 destination
处的文件夹。如果 destination 是一个文件名,它将复制然后重命名。

shutil.copy2(source, destination)则在copy上的基础上同时复制最后访问时间与修改时间。

shutil.copytree()将复制整个文件夹,以及它包含的文件夹和文件。

比如我们想备份VScode的所有宝贵插件(我这儿大约877M)到你想要的位置,就可以执行以下代码:

1
2
3
import os 
os.chdir('C:\\Users\\Administrator\\.vscode')
shutil.copytree('extensions', 'D:\\extensions_backup')

shutil.move(source, destination),将路径 source 处的文件移动到路径destination,如果存在则覆盖,并返回新位置的绝对路径的字符串。

1
2
shutil.move('C:\\bacon.txt', 'C:\\eggs') 
# 'C:\\eggs\\bacon.txt'

destination 路径也可以指定一个文件名。在下面的例子中,source 文件被移动并改名。

1
2
shutil.move('C:\\bacon.txt', 'C:\\eggs\\bacon2.txt') 
# 'C:\\eggs\\bacon2.txt'
1
2
shutil.move('C:\\bacon.txt', 'C:\\eggs\\') 
# 'C:\\eggs'

!!!: 如果没有 eggs 文件夹,move()就会将 bacon.txt 改名,变成名为 eggs 的文件。

1
2
# 若目标文件夹不存在,会触发FileNotFoundError
shutil.move('C:\\bacon.txt', 'C:\\does_not_exist\\eggs\\ham')

删除

注:删除后均不可恢复

方法
os.unlink(path) 删除 path 处的文件
os.rmdir(path) 删除 path 处的空文件夹
shutil.rmtree(path) 删除 path 处的文件夹,它包含的所有文件和文件夹都
会被删除。

一下展示了如何删除当前目录下所有的.pyc文件,

1
2
3
4
5
import os 
for filename in os.listdir():
if filename.endswith('.pyc'):
print(filename)
os.unlink(filename)

我们也可利send2trash 模块安全地删除文件,发送到计算机的垃圾箱或回收站中,防止你删除了不想删除的或者后悔删除的文件。

1
pip install send2trash
1
2
import send2trash 
send2trash.send2trash('testFile.txt')

归档文件(Compress)

利用 zipfile 模块中的函数,Python 程序可以创建和打开(或解压)ZIP 文件。

读取 ZIP 文件

首先我们调用 zipfile.ZipFile()函数,创建一个 ZipFile对象,并向它传入一个字符串,表示.zip 文件的文件名。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import zipfile, os
os.chdir('C:\\') # move to the folder with example.zip
exampleZip = zipfile.ZipFile('名著.zip')
[f.encode('cp437').decode('gbk') for f in exampleZip.namelist()]
# ['红楼梦.txt','水浒传.txt']
red_chamber = exampleZip.getinfo(exampleZip.namelist()[0])
red_chamber.file_size
# 2463064
red_chamber.compress_size
# 1058017
'压缩率:%s%%!' % (round(red_chamber
.compress_size/red_chamber.file_size, 2)) ##
# '压缩率:0.43%!'
exampleZip.close()

从 ZIP 文件中解压缩

ZipFile 对象的 extractall()方法从 ZIP 文件中解压缩所有文件和文件夹,放到当前工作目录中,如果传递给 extractall()方法的文件夹不存在,它会被创建。

1
2
3
exampleZip = zipfile.ZipFile('名著.zip') 
exampleZip.extractall()
exampleZip.close()

此时zip压缩包解压后的文件名是乱码,文件可以正常打开,内容没有乱码,待解决。

ZipFile 对象的 extract()方法从 ZIP 文件中解压缩单个文件。继续交互式环境中
的例子:

1
2
3
4
5
exampleZip = zipfile.ZipFile('红楼梦.zip') 
exampleZip.extract(exampleZip.namelist()[0])
exampleZip.extract(exampleZip.namelist()[0], 'D:\\new_folders')
'D:\\new_folders\\XXX.txt'
exampleZip.close()

创建和添加到 ZIP 文件

要创建你自己的压缩 ZIP 文件,必须以“写模式”打开 ZipFile 对象,即传入’w’作为第二个参数。

1
2
3
4
5
os.chdir('C:\\Users\\Administrator')
import zipfile
newZip = zipfile.ZipFile('.bash_history.zip', 'w')
newZip.write('.bash_history', compress_type=zipfile.ZIP_DEFLATED)
newZip.close()

REFERENCES