How to use glob() to find files recursively?
这就是我所拥有的:
1 | glob(os.path.join('src','*.c')) |
但我想搜索SRC的子文件夹。类似这样的事情会奏效:
1 2 3 4 | 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版开始,
1 2 3 4 | import glob for filename in glob.iglob('src/**/*.c', recursive=True): print(filename) |
如果需要列表,只需使用
对于匹配以点(.)开头的文件(如当前目录中的文件或基于UNIX的系统上的隐藏文件)的情况,请使用下面的
python 2.2到3.4
对于较旧的python版本,从python 2.2开始,使用
1 2 3 4 5 6 7 | 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版本,对每个文件名使用
与其他解决方案类似,但使用fnmatch.fnmatch而不是glob,因为os.walk已经列出了文件名:
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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 |
另外,使用生成器可以让您在找到每个文件时对其进行处理,而不是先查找所有文件,然后再对其进行处理。
我已经修改了glob模块以支持**递归的globbing,例如:
1 2 | >>> import glob2 >>> all_header_files = glob2.glob('src/**/*.c') |
https://github.com/miracle2k/python-glob2/
当您想为用户提供使用**语法的能力时很有用,因此单独使用os.walk()还不够好。
从python 3.4开始,可以在支持
1 2 3 4 | from pathlib import Path for file_path in Path('src').glob('**/*.c'): print(file_path) # do whatever you need with these files |
更新:从Python3.5开始,
1 2 3 4 5 6 7 8 9 10 | 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 |
您将希望使用
1 2 3 4 5 6 | 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)) |
这里有一个嵌套列表理解的解决方案,
1 2 3 4 | import os cfiles = [os.path.join(root, filename) for root, dirnames, filenames in os.walk('src') for filename in filenames if filename.endswith('.c')] |
它可以压缩成一个内衬:
1 | import os;cfiles=[os.path.join(r,f) for r,d,fs in os.walk('src') for f in fs if f.endswith('.c')] |
或概括为一个函数:
1 2 3 4 5 6 7 8 | 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') |
如果你确实需要完整的
1 2 3 4 5 6 7 8 9 10 | 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') |
最近我不得不用扩展名.jpg恢复我的照片。我运行photorec并恢复了4579个目录中220万个文件,扩展名种类繁多。通过下面的脚本,我可以在几分钟内选择50133个havin.jpg扩展名文件:
1 2 3 4 5 6 7 8 9 10 | #!/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) |
Johan和Bruno在规定的最低要求上提供了出色的解决方案。我刚刚发布了formic,它实现了Ant文件集和globs,可以处理这个和更复杂的场景。您的要求的实现是:
1 2 3 4 | import formic fileset = formic.FileSet(include="/src/**/*.c") for file_name in fileset.qualified_files(): print file_name |
基于其他答案,这是我当前的工作实现,它检索根目录中的嵌套XML文件:
1 2 3 | files = [] for root, dirnames, filenames in os.walk(myDir): files.extend(glob.glob(root +"/*.xml")) |
我真的很喜欢Python:)
另一种方法是只使用glob模块。只需在rglob方法中输入一个起始基目录和要匹配的模式,它将返回一个匹配文件名的列表。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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 |
除了建议的答案外,您还可以使用一些懒惰的一代和列表理解魔法:
1 2 3 4 5 6 | 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) |
除了在内存中容纳一行并避免不必要的列表之外,这还有一个很好的副作用,您可以使用类似于**运算符的方式使用它,例如,您可以使用
刚做的……它将以分层方式打印文件和目录
但我没有用火柴或走路
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | #!/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) |
或者用清单理解:
1 2 3 4 | >>> 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或正则表达式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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')]) |
下面是我的解决方案,使用列表理解在一个目录和所有子目录中递归搜索多个文件扩展名:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | import os, glob def _globrec(path, *exts): """ Glob recursively a directory and all subdirectories for multiple file extensions Note: Glob is case-insensitive, i. e. 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 |
没有fnmatch的johan dahlin答案的简化版本。
1 2 3 4 5 | 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'] |
我需要一个能在大目录下快速运行的python2.x解决方案。我以这个结尾:
1 2 3 4 | import subprocess foundfiles= subprocess.check_output("ls src/*.c src/**/*.c", shell=True) for foundfile in foundfiles.splitlines(): print foundfile |
注意,如果
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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) |
我在这篇文章中修改了最重要的答案。最近创建了这个脚本,它将遍历给定目录(searchdir)中的所有文件及其下的子目录…并打印文件名、rootdir、修改/创建日期和大小。
希望这能帮助别人…他们可以浏览目录并获取文件信息。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | 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 oot' 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)) |
这里有一个解决方案,它将模式与完整路径相匹配,而不仅仅是基本文件名。
它使用
1 2 3 4 5 6 7 8 9 10 11 | 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 |