一、引言
此前,本号分享过一篇用 os.listdir 来查找目录及子目录下的所有指定类型文件的文章,见:
《查找目录和子目录下所有指定类型的文件——os.listdir篇》
这篇文章提到,查找目录及子目录下的所有指定类型文件,除了可以用用 os.listdir 来实现之外,还可以用 os.walk 、glob 来实现。
后来,本号在介绍分词的时候,顺便介绍了用glob标准库来查找目录及子目录下的所有指定类型文件的方法,见:
现在,来分享一下用 os.walk 来查找目录及子目录下的所有指定类型文件的方法。
环境:64位Win 10中文版 + 64位Python 3.7.6

本书配套的电子版图书中的编码和文本处理知识也可以作为理工科教师和科研人员处理文本数据的参考资料之一,毕竟专门开辟章节介绍国家标准《通用规范汉字表》汉字处理的程序设计图书并不多见。



假定我们操作目录是 D:\ftp\a,该目录及子目录下的文件结构如下图所示。
我们用os.walk来查找其中指定类型的文件。
首先导入。
>>> from os import walk
复制
其次,准备一个变量存放目录:
>>> p = r"D:\ftp\a"
复制
然后就可以开工了:
>>> walk(p)
<generator object walk at 0x0000019E64F882C8>
复制
它居然返回一个生成器对象。关于生成器对象,具体请参考图书《Python程序设计(基于计算思维和新文科建设)》第169页及该页提到的相应章节。
这里我们直接转为list看它包含的元素。
>>> list(walk(p))
[('D:\\ftp\\a', ['b', 'c.docx'], ['a.doc', 'c.txt', 'D.DOC', 'readme']), ('D:\\ftp\\a\\b', [], ['bb.doc']), ('D:\\ftp\\a\\c.docx', [], ['cc.docx'])]
复制
我们可以不用转成列表,而是直接遍历它的元素:
>>> for e in list(walk(p)):
print(e)
('D:\\ftp\\a', ['b', 'c.docx'], ['a.doc', 'c.txt', 'D.DOC', 'readme'])
('D:\\ftp\\a\\b', [], ['bb.doc'])
('D:\\ftp\\a\\c.docx', [], ['cc.docx'])
复制
我们发现它的元素是三元组,通过考察上面图中给出的目录结构我们可以知道,每个三元组都对应目录 p 或者它下面的一个子目录,每个三元组的第一个元素是目录,第二个元素是该目录下的所有子目录列表,第三个元素是该目录下的所有文件列表。
第二个元素对我们来说没啥用,我们只需要把三元组中的第一个元素跟第三个元素(注意:第三个元素是列表)中的每个元素合成文件路径就行了。这样我们就能够得到获取目录及子目录下所有的文件。
现在我们给出从导入开始的完整代码:
>>> from os import walk
>>> from os.path import join
>>> p = r"D:\ftp\a"
>>> files = [join(p,f) for d,s,fs in walk(p) for f in fs]
>>> files
['D:\\ftp\\a\\a.doc', 'D:\\ftp\\a\\c.txt', 'D:\\ftp\\a\\D.DOC', 'D:\\ftp\\a\\readme', 'D:\\ftp\\a\\bb.doc', 'D:\\ftp\\a\\cc.docx']
复制
得到所有文件列表之后还需要按照文件扩展名进行筛选,可以用字符串对象的endswith方法来筛选。
但是,考虑到一些文件没有扩展名,还有的时候我们查找所有文件,不需要限制扩展名。所以,这个后续的考虑还很复杂。
不过,有人替我们考虑周全了,写了一段完整的代码,并且封装成了自定义函数,那就是自定义函数 find_file_walk。
图书《Python程序设计(基于计算思维和新文科建设)》第312页和313页给出了一个比较完美的自定义函数。
在上面的例子中定义了一个函数 find_files_walk,给定目录和文件类型之后,它可以查找任意指定的文件类型:
所有文件:让参数filetypelist=[] 即可
无扩展名:让参数filetypelist=[""] 即可
一种扩展名:例如JPG图片:让参数filetypelist=[".jpg"] 即可
多种扩展名:例如Word文件:让filetypelist=[".doc", ".docx"]即可
我们发现,该函数具有高度的灵活性,基本上能完美实现我们在某目录及其子目录下查找文件的功能需求。
上例中,我们把这个函数放入到自定义函数库 D:\mypy\myfunc.py中,需要的时候从自定义库 myfunc 导入该函数,会给我们查找文件带来极大的方便。
那么,如何创建自定义函数库并从自定义库中导入函数呢?本号此前刚好有两篇文章可以参考:
需要说明的是,自定义库的名字和位置都是可以更改的,只要Python能知道我们的自定义库放在哪里,我们的自定义库叫什么什么名字,我们要从自定义库中导入什么函数就行。
现在让我们回到本号上次发的批量处理文件模板:
有了本文的基础,大家再去回顾批量操作文件的代码模板,是不是对其中用到的自定义函数 find_files_walk 就很熟悉了?希望本文能对大家查找文件有所帮助。
六、图书目录