【Python】Python 遍历目录树及压缩文件

Python 遍历目录树及压缩文件

1. 遍历目录树

假定你希望对某个文件夹中的所有文件改名, 包括该文件夹中所有子文件夹中的所有文件。 也就是说,你希望遍历目录树,处理遇到的每个文件。 写程序完成这件事,可能需要一些技巧。 好在,Python提供了一个函数,替你处理这个过程。

这里有一个例子程序,针对目录树的遍历, 使用了 os.walk() 函数:

import os

for folderName, subfolders, filenames in os.walk(‘/tmp/’):
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('-' * 10)

The current folder is /tmp/
SUBFOLDER OF /tmp/: dest_backup
SUBFOLDER OF /tmp/: xx
SUBFOLDER OF /tmp/: .font-unix
SUBFOLDER OF /tmp/: systemd-private-d21d874a6c81438ebe00e91e126ce99a-apache2.service-Fq7esX
SUBFOLDER OF /tmp/: .ICE-unix
SUBFOLDER OF /tmp/: .XIM-unix
SUBFOLDER OF /tmp/: .X11-unix
SUBFOLDER OF /tmp/: systemd-private-d21d874a6c81438ebe00e91e126ce99a-systemd-logind.service-J6Dvi5
SUBFOLDER OF /tmp/: systemd-private-d21d874a6c81438ebe00e91e126ce99a-jupyterhub.service-T41S7m
SUBFOLDER OF /tmp/: systemd-private-d21d874a6c81438ebe00e91e126ce99a-ModemManager.service-CpuBqq
SUBFOLDER OF /tmp/: systemd-private-d21d874a6c81438ebe00e91e126ce99a-chrony.service-9dKXWa
FILE INSIDE /tmp/: new_chapter.ipynb
FILE INSIDE /tmp/: aliyun_assist_service.sock
FILE INSIDE /tmp/: AliyunAssistClientSingleLock.lock
FILE INSIDE /tmp/: chapter.ipynb

The current folder is /tmp/dest_backup
SUBFOLDER OF /tmp/dest_backup: new
SUBFOLDER OF /tmp/dest_backup: .ipynb_checkpoints
FILE INSIDE /tmp/dest_backup: sec05_practice1.ipynb
FILE INSIDE /tmp/dest_backup: sec02_pathlib.ipynb
FILE INSIDE /tmp/dest_backup: sec01_shutil.ipynb
FILE INSIDE /tmp/dest_backup: sec02_walktree.ipynb
FILE INSIDE /tmp/dest_backup: img3_1.png

FILE INSIDE /tmp/dest_backup: sec02-glob.ipynb

The current folder is /tmp/dest_backup/new
SUBFOLDER OF /tmp/dest_backup/new: foo
FILE INSIDE /tmp/dest_backup/new: hello1.txt
FILE INSIDE /tmp/dest_backup/new: hello2.txt

The current folder is /tmp/dest_backup/new/foo
FILE INSIDE /tmp/dest_backup/new/foo: foo.txt

The current folder is /tmp/dest_backup/.ipynb_checkpoints
FILE INSIDE /tmp/dest_backup/.ipynb_checkpoints: sec01_shutil-checkpoint.ipynb
FILE INSIDE /tmp/dest_backup/.ipynb_checkpoints: sec02_walktree-checkpoint.ipynb

The current folder is /tmp/xx
SUBFOLDER OF /tmp/xx: new
SUBFOLDER OF /tmp/xx: .ipynb_checkpoints
FILE INSIDE /tmp/xx: sec05_practice1.ipynb
FILE INSIDE /tmp/xx: sec02_pathlib.ipynb
FILE INSIDE /tmp/xx: sec01_shutil.ipynb
FILE INSIDE /tmp/xx: sec02_walktree.ipynb
FILE INSIDE /tmp/xx: img3_1.png
FILE INSIDE /tmp/xx: sec07_libarchive.ipynb
FILE INSIDE /tmp/xx: sec03_zipfile.ipynb
FILE INSIDE /tmp/xx: new.zip

FILE INSIDE /tmp/xx: sec02-glob.ipynb

The current folder is /tmp/xx/new
SUBFOLDER OF /tmp/xx/new: foo
FILE INSIDE /tmp/xx/new: hello1.txt
FILE INSIDE /tmp/xx/new: hello2.txt

The current folder is /tmp/xx/new/foo
FILE INSIDE /tmp/xx/new/foo: foo.txt

The current folder is /tmp/xx/.ipynb_checkpoints
FILE INSIDE /tmp/xx/.ipynb_checkpoints: sec01_shutil-checkpoint.ipynb
FILE INSIDE /tmp/xx/.ipynb_checkpoints: sec02_walktree-checkpoint.ipynb

The current folder is /tmp/.font-unix

The current folder is /tmp/.ICE-unix

The current folder is /tmp/.XIM-unix

The current folder is /tmp/.X11-unix

os.walk() 函数被传入一个字符串值,即一个文件夹的路径。 你可以在一个 for 循环语句中使用 os.walk() 函数, 遍历目录树,就像使用 range() 函数遍历一个范围的数字一样。 不像 range() , os.walk() 在循环的每次迭代中,返回3个值:

当前文件夹名称的字符串。

当前文件夹中子文件夹的字符串的列表。

当前文件夹中文件的字符串的列表。

所谓当前文件夹,是指 for 循环当前迭代的文件夹。 程序的当前工作目录,不会因为 os.walk() 而改变。

就像你可以在代码 for i in range(lO): 中选择变量名称 i 一样,你也可以选择前面列出来的3个字的变量名称。 我通常使用 foldemame 、 subfolders 和 filenames 。

因为 os.walk() 返回字符串的列表, 保存在 subfolder 和 filename 变量中, 所以你可以在它们自己的 for 循环中使用这些列表。 用你自己定制的代码,取代 print() 函数调用 (或者如果不需要,就删除 for 循环)。

2. 用 zipfile 模块压缩文件

你可能熟悉ZIP文件(带有.zip文件扩展名),它可以包含许多其他文件的压缩内容。 压缩一个文件会减少它的大小,这在因特网上传输时很有用。 因为一个ZIP文件可以包含多个文件和子文件夹,所以它是一种很方便的方式,将多个文件打包成一个文件。 这个文件叫做“归档文件”,然后可以用作电子邮件的附件,或其他用途。

利用 zipfile 模块中的函数,Python程序可以创建和打开(或解压)ZIP文件。 假定你有一个名为 new.zip 的文件。

可以从 http://nostarch.com/automatestuff/ 下载这个ZIP文件,或者利用计算机上 已有的一个ZIP文件,接着完成下面的操作。

2.1. 读取 ZIP 文件

要读取ZIP文件的内容,首先必须创建一个 ZipFile 对象 (请注意大写首字母Z和F)。 ZipFile 对象在概念上与 File 对象相似:它们是一些值,程序通过它们与文件打交道。 要创建一个ZipFile 对象,就调用 zipfile.ZipFile() 函数, 向它传入一个字符串,如 .zip 文件的文件名。 请注意, zipfile 是Python模块的名称, ZipFile() 是函数的名称。

例如,在交互式环境中输入以下代码:

import zipfile, os

move to the folder with example.zip

os.chdir(‘.’)
exampleZip = zipfile.ZipFile(‘new.zip’)
exampleZip.namelist()
[‘new/’, ‘new/hello1.txt’, ‘new/hello2.txt’]
spamInfo = exampleZip.getinfo(‘new/hello1.txt’)
spamInfo.file_size
13
spamInfo.compress_size
15
‘Compressed file is %sx smaller!’ % (round(spamInfo.file_size / spamInfo.compress_size, 2))
‘Compressed file is 0.87x smaller!’
exampleZip.close()
ZipFile 对象有一个 namelist() 方法, 返回ZIP文件中包含的所有文件和文件夹的字符串的列表。 这些字符串可以传递给 ZipFile 对象的 getinfo() 方法, 返回一个关于特定文件的 Ziplnfo 对象。 Ziplnfo 对象有自己的属性,诸如表示字节数的 file_size 和 compress_size , 它们分别表示原来文件大小和压缩后文件大小。 ZipFile 对象表不整个归档文件, 而 ZipInfo 对象则保存该归档文件中每个文件的有用信息。

‘Compressed file is %sx smaller!’ % (round(spamInfo.file_size / spamInfo.compress_size, 2))的命令计算出 example.zip 压缩的效率, 用压缩后文件的大小除以原来文件的大小,并以%s字符串格式打印出这一信息。

2.2. 从 ZIP 文件中解压缩

ZipFile 对象的 extractall() 方法从 ZIP 文件中解压缩所有文件和文件夹,放到当前工作目录中。

import zipfile, os
os.chdir(‘.’) # move to the folder with example.zip
exampleZip = zipfile.ZipFile(‘new.zip’)
exampleZip.extractall(‘xx_out’)
exampleZip.close()
运行这段代码后, example.zip 的内容将被解压缩到 xx_out 文件夹。 或者,如果 extractall() 没有使用参数,会解压缩到当前文件夹。 如果传递给 extractall() 方法的文件夹不存在,它会被创建。

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

exampleZip = zipfile.ZipFile(‘new.zip’)
exampleZip.extract(‘new/hello1.txt’)
‘/home/bk/book-jubook/python/jubook_python/pt04_essential/ch03_file/new/hello1.txt’
exampleZip.extract(‘new/hello2.txt’,‘.’)
exampleZip.close()
传递给 extract() 的字符串, 必须匹配 namelist()返回的字符串列表中的一个。 或者,你可以向 extract() 传递第二个参数, 将文件解压缩到指定的文件夹,而不是当前工作目录。 如果第二个参数指定的文件夹不存在, Python 就会创建它。 extract() 的返回值是被压缩后文件的绝对路径。

2.3. 创建和添加到ZIP文件

要创建你自己的压缩ZIP文件,必须以“写模式”打开 ZipFile 对象, 即传入 'w’作为第二个参数(这类似于向 open()函数传入 ‘w’ 以写模式打开一个文本文件)。

如果向 ZipFile 对象的 write() 方法传入一个路径, Python就会压缩该路径所指的文件,将它加到ZIP文件中。 write() 方法的第一个参数是一个字符串,代表要添 加的文件名。第二个参数是“压缩类型”参数,它告诉计算机使用怎样的算法来压 缩文件。可以总是将这个值设置为 zipfile.ZIP_DEFLATHD (这指定了 deflate 压缩算法,它对各种类型的数据都很有效)。 在交互式环境中输入以下代码:

import shutil

shutil.copy(‘new.zip’, ‘xx_new.zip’)

import zipfile
newZip = zipfile.ZipFile(‘xx_new2.zip’, ‘w’)
newZip.write(‘chapter.ipynb’,compress_type=zipfile.ZIP_DEFLATED)
newZip.close()
这段代码将创建一个新的ZIP文件,名为 xx_new.zip , 它包含 chapter.ipynb 压缩后的内容。

要记住,就像写入文件一样,写模式( w )将擦除ZIP文件中所有原有的内容。 如果只是希望将文件添加到原有的 ZIP 文件中, 就要向 zipfile.ZipFile() 传入 ‘a’ 作为第二个参数, 以添加模式打开 ZIP 文件。

你可能感兴趣的:(Python,技术研发,技术工具,python,java,前端)