>>> from env_helper import info; info()
页面更新时间: 2023-06-30 19:18:41
运行环境:
    Linux发行版本: Debian GNU/Linux 12 (bookworm)
    操作系统内核: Linux-6.1.0-9-amd64-x86_64-with-glibc2.36
    Python版本: 3.11.2

3.4. 遍历目录树

假定你希望对某个文件夹中的所有文件改名, 包括该文件夹中所有子文件夹中的所有文件。 也就是说,你希望遍历目录树,处理遇到的每个文件。 写程序完成这件事,可能需要一些技巧。 好在,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: sec07_libarchive.ipynb
FILE INSIDE /tmp/dest_backup: sec03_zipfile.ipynb
FILE INSIDE /tmp/dest_backup: new.zip
FILE INSIDE /tmp/dest_backup: sec06_practice2.ipynb
FILE INSIDE /tmp/dest_backup: img3_2.png
FILE INSIDE /tmp/dest_backup: news.zip
FILE INSIDE /tmp/dest_backup: sec04_renam.ipynb
FILE INSIDE /tmp/dest_backup: chapter.ipynb
FILE INSIDE /tmp/dest_backup: ch09_file_文件操作_1.zip
FILE INSIDE /tmp/dest_backup: 2-18-2018测试日期信息.txt
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: sec06_practice2.ipynb
FILE INSIDE /tmp/xx: img3_2.png
FILE INSIDE /tmp/xx: news.zip
FILE INSIDE /tmp/xx: sec04_renam.ipynb
FILE INSIDE /tmp/xx: chapter.ipynb
FILE INSIDE /tmp/xx: ch09_file_文件操作_1.zip
FILE INSIDE /tmp/xx: 2-18-2018测试日期信息.txt
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个字的变量名称。 我通常使用 foldemamesubfoldersfilenames

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