如何递归查找文件?
我想要在一个文件夹里递归地列出所有文件。现在我的文件夹结构是这样的:
src/main.c
src/dir/file1.c
src/another-dir/file2.c
src/another-dir/nested/files/file3.c
我试过这样做:
from glob import glob
glob(os.path.join('src','*.c'))
但是这样只能获取到src
子文件夹下直接的文件,比如我能得到main.c
,但却得不到file1.c
、file2.c
等文件。
from glob import glob
glob(os.path.join('src','*.c'))
glob(os.path.join('src','*','*.c'))
glob(os.path.join('src','*','*','*.c'))
glob(os.path.join('src','*','*','*','*.c'))
显然,这种方法有限且不够灵活,那我该怎么做才能正确地列出所有文件呢?
28 个回答
123
这个方法和其他解决方案类似,不过它用的是fnmatch.fnmatch,而不是glob,因为os.walk已经列出了文件名:
import os, fnmatch
def find_files(directory, pattern):
for root, dirs, files in os.walk(directory):
for basename in files:
if fnmatch.fnmatch(basename, pattern):
filename = os.path.join(root, basename)
yield filename
for filename in find_files('src', '*.c'):
print 'Found C source:', filename
另外,使用生成器可以让你在找到每个文件时就处理它,而不是先找到所有文件,然后再处理它们。
215
对于 Python 版本大于等于 3.5 的情况,你可以使用 **
和 recursive=True
,也就是说:
import glob
for f in glob.glob('/path/**/*.c', recursive=True):
print(f)
如果
recursive
设置为True
(默认是False
),那么模式**
会匹配任何文件以及零个或多个目录
和子目录
。如果这个模式后面跟着一个os.sep
,那么只会匹配目录和子目录
。
1803
有几种方法可以做到这一点:
pathlib.Path().rglob()
可以使用来自pathlib
模块的pathlib.Path().rglob()
,这个模块是在Python 3.5中引入的。
from pathlib import Path
for path in Path('src').rglob('*.c'):
print(path.name)
glob.glob()
如果你不想使用pathlib,可以使用glob.glob()
:
from glob import glob
for filename in glob('src/**/*.c', recursive=True):
print(filename)
如果你需要匹配以点(.
)开头的文件,比如当前目录中的文件或Unix系统中的隐藏文件,可以使用下面的os.walk()
解决方案。
os.walk()
对于旧版本的Python,可以使用os.walk()
来递归遍历一个目录,并用fnmatch.filter()
来匹配简单的表达式:
import fnmatch
import os
matches = []
for root, dirnames, filenames in os.walk('src'):
for filename in fnmatch.filter(filenames, '*.c'):
matches.append(os.path.join(root, filename))
这个版本在处理大量文件时可能会更快,因为pathlib模块相对于os.walk()
来说有一些额外的开销。