使用Glob()在Python中recursion地查找文件?

这是我的:

glob(os.path.join('src','*.c')) 

但我想searchsrc的子文件夹。 像这样的东西可以工作:

 glob(os.path.join('src','*.c')) glob(os.path.join('src','*','*.c')) glob(os.path.join('src','*','*','*.c')) glob(os.path.join('src','*','*','*','*.c')) 

但这显然是有限的,笨重的。

Python 3.5+

从Python版本3.5开始, glob模块支持"**"指令(仅当您传递recursive标志时才被parsing):

 import glob for filename in glob.iglob('src/**/*.c', recursive=True): print(filename) 

如果你需要一个列表,只需使用glob.glob而不是glob.iglob

Python 2.2到3.4

对于较早的Python版本,从Python 2.2开始,使用os.walkrecursion遍历一个目录,使用fnmatch.filter来匹配一个简单的expression式:

 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)) 

Python 2.1及更早的版本

对于更老的Python版本,对每个文件名使用glob.glob而不是fnmatch.filter

与其他解决scheme类似,但使用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 

此外,使用生成器允许您处理每个文件,因为它被发现,而不是find所有的文件,然后处理它们。

我修改了glob模块来支持recursion通配,例如:

 >>> import glob2 >>> all_header_files = glob2.glob('src/**/*.c') 

https://github.com/miracle2k/python-glob2/

当你想要为用户提供使用**语法的能力时很有用,因此os.walk()本身不够好。

从Python 3.4开始,可以在新的pathlib模块中使用其中一个Path类的glob()方法,该模块支持**通配符。 例如:

 from pathlib import Path for file_path in Path('src').glob('**/*.c'): print(file_path) # do whatever you need with these files 

更新:从Python 3.5开始, glob.glob()也支持相同的语法。

 import os import fnmatch def recursive_glob(treeroot, pattern): results = [] for base, dirs, files in os.walk(treeroot): goodfiles = fnmatch.filter(files, pattern) results.extend(os.path.join(base, f) for f in goodfiles) return results 

fnmatch给出了与glob完全相同的模式,所以这对于非常接近语义的glob.glob是一个很好的替代。 一个迭代版本(例如一个生成器),IOW代替glob.iglob ,是一个微不足道的适应(只是yield中间结果,而不是extend一个结果列表返回到最后)。

你会想使用os.walk收集符合你的标准的文件名。 例如:

 import os cfiles = [] for root, dirs, files in os.walk('src'): for file in files: if file.endswith('.c'): cfiles.append(os.path.join(root, file)) 

下面是嵌套列表os.walkos.walk和简单的后缀匹配代替glob的解决scheme:

 import os cfiles = [os.path.join(root, filename) for root, dirnames, filenames in os.walk('src') for filename in filenames if filename.endswith('.c')] 

它可以被压缩成一行:

 import os;cfiles=[os.path.join(r,f) for r,d,fs in os.walk('src') for f in fs if f.endswith('.c')] 

或者泛化为一个函数:

 import os def recursive_glob(rootdir='.', suffix=''): return [os.path.join(looproot, filename) for looproot, _, filenames in os.walk(rootdir) for filename in filenames if filename.endswith(suffix)] cfiles = recursive_glob('src', '.c') 

如果你确实需要glob风格的模式,你可以按照Alex和Bruno的例子来使用fnmatch

 import fnmatch import os def recursive_glob(rootdir='.', pattern='*'): return [os.path.join(looproot, filename) for looproot, _, filenames in os.walk(rootdir) for filename in filenames if fnmatch.fnmatch(filename, pattern)] cfiles = recursive_glob('src', '*.c') 

Johan和Bruno在最低要求上提供了很好的解决scheme。 我刚刚发布了Formic ,它实现了可以处理这个和更复杂的场景的Ant FileSet和Globs 。 您的要求的实现是:

 import formic fileset = formic.FileSet(include="/src/**/*.c") for file_name in fileset.qualified_files(): print file_name 

基于其他答案,这是我目前的工作实现,它检索根目录中嵌套的XML文件:

 files = [] for root, dirnames, filenames in os.walk(myDir): files.extend(glob.glob(root + "/*.xml")) 

我真的很开心与python:)

最近我不得不恢复我的图片与扩展名.jpg。 我运行photorec并恢复了4579个目录中的220万个文件,具有极其多样的扩展。通过下面的脚本,我能够在几分钟内select50133个文件havin .jpg扩展名:

 #!/usr/binenv python2.7 import glob import shutil import os src_dir = "/home/mustafa/Masaüstü/yedek" dst_dir = "/home/mustafa/Genel/media" for mediafile in glob.iglob(os.path.join(src_dir, "*", "*.jpg")): #"*" is for subdirectory shutil.copy(mediafile, dst_dir) 

另一种使用glob模块的方法。 只要将rglob方法与一个起始的基本目录和一个要匹配的模式相结合,就会返回一个匹配的文件名列表。

 import glob import os def _getDirs(base): return [x for x in glob.iglob(os.path.join( base, '*')) if os.path.isdir(x) ] def rglob(base, pattern): list = [] list.extend(glob.glob(os.path.join(base,pattern))) dirs = _getDirs(base) if len(dirs): for d in dirs: list.extend(rglob(os.path.join(base,d), pattern)) return list 

除了build议的答案之外,你可以用一些懒惰的代和魔法列表来理解:

 import os, glob, itertools results = itertools.chain.from_iterable(glob.iglob(os.path.join(root,'*.c')) for root, dirs, files in os.walk('src')) for f in results: print(f) 

除了一行代码和避免不必要的内存列表,这也有很好的副作用,你可以像**运算符那样使用它,例如,你可以使用os.path.join(root, 'some/path/*.c') ,以便获取具有该结构的src的所有子目录中的所有.c文件。

Johan Dahlin的答案简化版,没有fnmatch 。

 import os matches = [] for root, dirnames, filenames in os.walk('src'): matches += [os.path.join(root, f) for f in filenames if f[-2:] == '.c'] 

或者用列表理解:

  >>> base = r"c:\User\xtofl" >>> binfiles = [ os.path.join(base,f) for base, _, files in os.walk(root) for f in files if f.endswith(".jpg") ] 

只是做了这个..它将以分层的方式打印文件和目录

但我没有使用fnmatch或步行

 #!/usr/bin/python import os,glob,sys def dirlist(path, c = 1): for i in glob.glob(os.path.join(path, "*")): if os.path.isfile(i): filepath, filename = os.path.split(i) print '----' *c + filename elif os.path.isdir(i): dirname = os.path.basename(i) print '----' *c + dirname c+=1 dirlist(i,c) c-=1 path = os.path.normpath(sys.argv[1]) print(os.path.basename(path)) dirlist(path) 

那个使用fnmatch或正则expression式:

 import fnmatch, os def filepaths(directory, pattern): for root, dirs, files in os.walk(directory): for basename in files: try: matched = pattern.match(basename) except AttributeError: matched = fnmatch.fnmatch(basename, pattern) if matched: yield os.path.join(root, basename) # usage if __name__ == '__main__': from pprint import pprint as pp import re path = r'/Users/hipertracker/app/myapp' pp([x for x in filepaths(path, re.compile(r'.*\.py$'))]) pp([x for x in filepaths(path, '*.py')]) 

这是我的解决scheme,使用列表parsing在目录和所有子目录中recursionsearch多个文件扩展名:

 import os, glob def _globrec(path, *exts): """ Glob recursively a directory and all subdirectories for multiple file extensions Note: Glob is case-insensitive, ie for '\*.jpg' you will get files ending with .jpg and .JPG Parameters ---------- path : str A directory name exts : tuple File extensions to glob for Returns ------- files : list list of files matching extensions in exts in path and subfolders """ dirs = [a[0] for a in os.walk(path)] f_filter = [d+e for d in dirs for e in exts] return [f for files in [glob.iglob(files) for files in f_filter] for f in files] my_pictures = _globrec(r'C:\Temp', '\*.jpg','\*.bmp','\*.png','\*.gif') for f in my_pictures: print f 
 import sys, os, glob dir_list = ["c:\\books\\heap"] while len(dir_list) > 0: cur_dir = dir_list[0] del dir_list[0] list_of_files = glob.glob(cur_dir+'\\*') for book in list_of_files: if os.path.isfile(book): print(book) else: dir_list.append(book) 

我修改了这个post中的最佳答案..最近创build了这个脚本,它将遍历给定目录(searchdir)及其下的子目录中的所有文件…并打印文件名,rootdir,修改/创builddate和尺寸。

希望这可以帮助别人…他们可以走的目录,并获得fileinfo。

 import time import fnmatch import os def fileinfo(file): filename = os.path.basename(file) rootdir = os.path.dirname(file) lastmod = time.ctime(os.path.getmtime(file)) creation = time.ctime(os.path.getctime(file)) filesize = os.path.getsize(file) print "%s**\t%s\t%s\t%s\t%s" % (rootdir, filename, lastmod, creation, filesize) searchdir = r'D:\Your\Directory\Root' matches = [] for root, dirnames, filenames in os.walk(searchdir): ## for filename in fnmatch.filter(filenames, '*.c'): for filename in filenames: ## matches.append(os.path.join(root, filename)) ##print matches fileinfo(os.path.join(root, filename)) 

这是一个解决scheme,将模式匹配完整的path,而不仅仅是基本文件名。

它使用fnmatch.translate将glob风格的模式转换为正则expression式,然后将其与遍历目录时find的每个文件的完整path进行匹配。

re.IGNORECASE是可选的,但在Windows上是可取的,因为文件系统本身不区分大小写。 (我没有打扰编译正则expression式,因为文档表明它应该在内部caching。)

 import fnmatch import os import re def findfiles(dir, pattern): patternregex = fnmatch.translate(pattern) for root, dirs, files in os.walk(dir): for basename in files: filename = os.path.join(root, basename) if re.search(patternregex, filename, re.IGNORECASE): yield filename 

我需要一个python 2.x解决scheme,可以在大型目录上快速运行。
我解决了这个问题:

 import subprocess foundfiles= subprocess.check_output("ls src/*.c src/**/*.c", shell=True) for foundfile in foundfiles.splitlines(): print foundfile 

请注意,如果ls找不到任何匹配的文件,您可能需要一些exception处理。