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/: delicious ---------- The current folder is /tmp/delicious SUBFOLDER OF /tmp/delicious: walnut ---------- The current folder is /tmp/delicious/walnut SUBFOLDER OF /tmp/delicious/walnut: waffles ---------- The current folder is /tmp/delicious/walnut/waffles ----------
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
循环)。
import os
def find_files_by_ext(root_dir, extension):
"""查找指定扩展名的文件"""
for dirpath, _, filenames in os.walk(root_dir):
for filename in filenames:
if filename.endswith(extension):
print(os.path.join(dirpath, filename))
查找所有.py
文件
find_files_by_ext('/path/to/project', '.py')
- 处理符号链接
import os
def walk_dir_handle_links(path):
"""处理符号链接的目录遍历"""
for dirpath, dirnames, filenames in os.walk(path):
# 避免跟随符号链接导致无限循环
dirnames[:] = [d for d in dirnames
if not os.path.islink(os.path.join(dirpath, d))]
# 处理文件
for filename in filenames:
full_path = os.path.join(dirpath, filename)
if os.path.islink(full_path):
print(f"符号链接: {full_path} -> {os.readlink(full_path)}")
else:
print(f"文件: {full_path}")
- 性能优化建议
对于大型目录树:优先使用
os.scandir()
(比os.listdir()
更快)避免重复stat调用:使用
os.DirEntry
对象的属性(如entry.is_file()
)并行处理:对于非常大的目录,可以考虑使用多线程/多进程