Python glob多个文件types

有没有更好的方法来使用Python中的glob.glob获取多个文件types的列表,如.txt,.mdown和.markdown? 现在我有这样的东西:

projectFiles1 = glob.glob( os.path.join(projectDir, '*.txt') ) projectFiles2 = glob.glob( os.path.join(projectDir, '*.mdown') ) projectFiles3 = glob.glob( os.path.join(projectDir, '*.markdown') ) 

也许有更好的办法,但是怎么样:

 >>> import glob >>> types = ('*.pdf', '*.cpp') # the tuple of file types >>> files_grabbed = [] >>> for files in types: ... files_grabbed.extend(glob.glob(files)) ... >>> files_grabbed # the list of pdf and cpp files 

也许还有另一种方法,等等,以防别人想出更好的答案。

连锁结果:

 import itertools as it, glob def multiple_file_types(*patterns): return it.chain.from_iterable(glob.iglob(pattern) for pattern in patterns) 

然后:

 for filename in multiple_file_types("*.txt", "*.sql", "*.log"): # do stuff 
 from glob import glob files = glob('*.gif') files.extend(glob('*.png')) files.extend(glob('*.jpg')) print(files) 

如果你需要指定一个path,为了简单起见,循环匹配模式并在循环中保持连接:

 from os.path import join from glob import glob files = [] for ext in ('*.gif', '*.png', '*.jpg'): files.extend(glob(join("path/to/dir", ext))) print(files) 

与glob是不可能的。 你只能使用:
*匹配一切
? 匹配任何单个字符
[seq]匹配seq中的任何字符
[!seq]匹配不在seq中的任何字符

使用os.listdir和一个正则expression式来检查模式:

 for x in os.listdir('.'): if re.match('.*\.txt|.*\.sql', x): print x 

glob返回一个列表:为什么不多次运行它并连接结果呢?

 from glob import glob ProjectFiles = glob('*.txt') + glob('*.mdown') + glob('*markdown') 

例如,对于多个文件夹中的*.mp3*.flac ,您可以执行以下操作:

 mask = r'music/*/*.[mf][pl][3a]*' glob.glob(mask) 

这个想法可以扩展到更多的文件扩展名, 你必须检查这些组合将不匹配你可能在这些文件夹上有任何其他不需要的文件扩展名。 所以, 小心这个。

我发布了Formic ,它以类似于Apache Ant的FileSet和Globs的方式实现了多个包含。

search可以执行:

 import formic patterns = ["*.txt", "*.markdown", "*.mdown"] fileset = formic.FileSet(directory=projectDir, include=patterns) for file_name in fileset.qualified_files(): # Do something with file_name 

由于实现了完整的Ant glob,因此可以为每个模式包含不同的目录,因此,您可以在一个子目录中仅select这些.txt文件,而在另一个子目录中select.markdown,例如:

 patterns = [ "/unformatted/**/*.txt", "/formatted/**/*.mdown" ] 

我希望这有帮助。

不是glob ,但是这里是使用列表理解的另一种方法:

 extensions = 'txt mdown markdown'.split() projectFiles = [f for f in os.listdir(projectDir) if os.path.splitext(f)[1][1:] in extensions] 

在来到这里寻求帮助之后,我做出了自己的解决scheme,并想分享它。 它基于user2363986的答案,但我认为这是更具扩展性。 意思是,如果你有1000个扩展,代码仍然看起来有些优雅。

 from glob import glob directoryPath = "C:\\temp\\*." fileExtensions = [ "jpg", "jpeg", "png", "bmp", "gif" ] listOfFiles = [] for extension in fileExtensions: listOfFiles.extend( glob( directoryPath + extension )) for file in listOfFiles: print(file) # Or do other stuff 

以下函数_glob为多个文件扩展名。

 import glob import os def _glob(path, *exts): """Glob for multiple file extensions Parameters ---------- path : str A file name without extension, or directory name exts : tuple File extensions to glob for Returns ------- files : list list of files matching extensions in exts in path """ path = os.path.join(path, "*") if os.path.isdir(path) else path + "*" return [f for files in [glob.glob(path + ext) for ext in exts] for f in files] files = _glob(projectDir, ".txt", ".mdown", ".markdown") 

这是一个Python 3.4+ pathlib解决scheme:

 exts = ".pdf", ".doc", ".xls", ".csv", ".ppt" filelist = (str(i) for i in map(pathlib.Path, os.listdir(src)) if i.suffix.lower() in exts and not i.stem.startswith("~")) 

它也忽略以~开头的所有文件名。

你可以尝试做一个手动列表比较现有的扩展和你需要的。

 ext_list = ['gif','jpg','jpeg','png']; file_list = [] for file in glob.glob('*.*'): if file.rsplit('.',1)[1] in ext_list : file_list.append(file) 

你可以使用filter:

 import os import glob projectFiles = filter( lambda x: os.path.splitext(x)[1] in [".txt", ".mdown", ".markdown"] glob.glob(os.path.join(projectDir, "*")) ) 

你也可以像这样使用reduce()

 import glob file_types = ['*.txt', '*.mdown', '*.markdown'] project_files = reduce(lambda list1, list2: list1 + list2, (glob.glob(t) for t in file_types)) 

这会为glob.glob()为每个模式创build一个列表, glob.glob()它们减less到一个列表。

 import os import glob import operator from functools import reduce types = ('*.jpg', '*.png', '*.jpeg') lazy_paths = (glob.glob(os.path.join('my_path', t)) for t in types) paths = reduce(operator.add, lazy_paths, []) 

https://docs.python.org/3.5/library/functools.html#functools.reduce https://docs.python.org/3.5/library/operator.html#operator.add

一个class轮,只是为了它的地狱

 folder = "C:\\multi_pattern_glob_one_liner" files = [item for sublist in [glob.glob(folder + ext) for ext in ["/*.txt", "/*.bat"]] for item in sublist] 

输出:

 ['C:\\multi_pattern_glob_one_liner\\dummy_txt.txt', 'C:\\multi_pattern_glob_one_liner\\dummy_bat.bat'] 

glob多个文件types,您需要在循环中多次调用glob()函数。 由于这个函数返回一个列表,你需要连接列表。

比如这个函数做这个工作:

 import glob import os def glob_filetypes(root_dir, *patterns): return [path for pattern in patterns for path in glob.glob(os.path.join(root_dir, pattern))] 

简单的用法:

 project_dir = "path/to/project/dir" for path in sorted(glob_filetypes(project_dir, '*.txt', '*.mdown', '*.markdown')): print(path) 

你也可以使用glob.iglob()来创build一个迭代器:

返回一个迭代器,其产生与glob()相同的值,而不是实际同时存储它们。

 def iglob_filetypes(root_dir, *patterns): return (path for pattern in patterns for path in glob.iglob(os.path.join(root_dir, pattern))) 

一个glob,许多扩展…但不完美的解决scheme(可能匹配其他文件)。

 filetypes = ['tif', 'jpg'] filetypes = zip(*[list(ft) for ft in filetypes]) filetypes = ["".join(ch) for ch in filetypes] filetypes = ["[%s]" % ch for ch in filetypes] filetypes = "".join(filetypes) + "*" print(filetypes) # => [tj][ip][fg]* glob.glob("/path/to/*.%s" % filetypes) 

这应该工作:

 import glob extensions = ('*.txt', '*.mdown', '*.markdown') for i in extensions: for files in glob.glob(i): print (files)