遍历目录树,即将一个目录中的所有文件都查询一遍,包含子目录中的文件,是一种经常会使用到的编程小技巧。在遍历过程中,叠加自己希望进行的操作,比如统计某一种类型的文件数量,或者对图片文件进行自动化压缩等等,可以实现很多非常有价值的功能。
Python编码时,使用递归来遍历,代码短小精干!
本文给出一个递归遍历目录树的Python代码框架, 此框架所使用的callback函数,只是仅仅将文件名称(普通文件)打印出来, 各位同学可以直接使用这个代码框架,修改callback函数,就可以实现自己的特殊功能需求。
代码框架
直接上代码吧:
#!/usr/bin/env python3
import os
import sys
from stat import *
def walktree(top, callback):
"""walk file tree from position top,
for each file, callback is called."""
for f in os.listdir(top):
pathname = os.path.join(top, f)
try:
mode = os.stat(pathname, follow_symlinks=False).st_mode
except:
continue
if S_ISDIR(mode):
# directory, recurse into it
walktree(pathname, callback)
else:
# file, whatever type, make the call back function
callback(pathname)
return
def printfile(file):
print('get to', file)
if __name__ == '__main__':
if (os.path.isabs(sys.argv[1]) and
os.path.exists(sys.argv[1])):
walktree(sys.argv[1], printfile)
代码解释
以上代码,关键是walktree这个递归调用自己的函数。函数入参top是一个绝对路径,在调用walktree之前判断是否有效,这个路径是遍历目录树开始的地方;入参callback是回调函数,对于每一个找到的文件,调用此函数进行处理。
以上代码使用printfile函数作为测试用回调函数,功能仅仅只是打印出pathname而已。根据您的需要,可以发挥的地方,也是这里。你可以统计某种类型的文件数量,对特种类型的文件进行某种你需要的处理等等。
一个细节:os.stat()函数的调用,指定了不要follow symbolic link file,这样保证了链接文件也能够被回调函数访问到,并且路径不会出现循环往复(如果有符号链接文件,链接的是一个路径)。
以上代码,用到了os.path模块的几个函数,用到了stat模块的函数,还有os模块的两个函数。
测试
假设以上代码存放在walktree.py文件中,你可以用下面这行命令来测试:
$sudo python3 walktree.py /
然后,你会看到所有的文件飞快地打印在屏幕上,由于输入的top参数是/,这是根路径,屏幕上文件名的打印,会持续好一会儿。sudo是为了防止permission deny的情况发生。
问题和局限
调用os.stat()函数的时候,no follow符号链接带来了一个问题,如果你用这段代码编译某个路径下的所有文件,如果有的文件是符号链接,并且链接的位置在这个top路径外面,那么这个文件本身将不会被访问到。
我在测试上面这段代码的时候,发现os.stat()函数有失败的情况,os.listdir()函数统计到了这个文件,但是在具体访问的时候却发现文件不存在,系统报FileNotFoundError异常。这样的异常基本上发生在与OS运行密切相关的路径中,因此加上了try...except结构。如果您还想对这样的异常进行处理,请自行在continue之前增加处理代码。对于一般用户文件,不会出现这样的异常。
-- EOF --