递归遍历目录树

2019年6月22日 / 56次阅读 / Last Modified 2019年8月18日
遍历文件

遍历目录树,即将一个目录中的所有文件都查询一遍,包含子目录中的文件,是一种经常会使用到的编程小技巧。在遍历过程中,叠加自己希望进行的操作,比如统计某一种类型的文件数量,或者对图片文件进行自动化压缩等等,可以实现很多非常有价值的功能。

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之前增加处理代码。对于一般用户文件,不会出现这样的异常。

python标准库os模块也提供了一个类似的遍历目录树的函数os.walk

-- EOF --

本文链接:https://www.pynote.net/archives/294

留言区

《递归遍历目录树》有1条留言

电子邮件地址不会被公开。 必填项已用*标注

  • 麦新杰

    我用本文介绍的递归遍历方法,做了一个遍历JPG文件做无损压缩的工具:https://www.pynote.net/archives/882 [回复]


前一篇:
后一篇:

More

麦新杰的Python笔记

Ctrl+D 收藏本页


©Copyright 麦新杰 Since 2019 Python笔记

go to top