使用fnmatch.filter按多个可能的文件扩展名筛选文件

tyr*_*dis 31 python filesystems

给出以下python代码:

for root, dirs, files in os.walk(directory):
    for filename in fnmatch.filter(files, '*.png'):
        pass
Run Code Online (Sandbox Code Playgroud)

如何过滤多个分机?在这种特殊情况下,我希望得到所有以*.png,*.gif,*.jpg或*.jpeg结尾的文件.

现在我想出来了

for root, dirs, files in os.walk(directory):
    for extension in ['jpg', 'jpeg', 'gif', 'png']:
        for filename in fnmatch.filter(files, '*.' + extension):
            pass
Run Code Online (Sandbox Code Playgroud)

但我认为它不是很优雅和高效.

有人有更好的主意吗?

eum*_*iro 44

如果您只需要检查扩展名(即没有其他通配符),为什么不简单地使用基本的字符串操作?

for root, dirs, files in os.walk(directory):
    for filename in files:
        if filename.endswith(('.jpg', '.jpeg', '.gif', '.png')):
            pass
Run Code Online (Sandbox Code Playgroud)

  • 请注意,此方法区分大小写,因此例如名为`annoying.GIF`的文件将不包含在上面的示例中.这可以通过规范化文件名来解决:`... if filename.lower().endswith(('.jpg','.jpeg','.gif','.png'))...` (11认同)

Sve*_*ach 8

我认为你的代码实际上很好.如果您只想触摸每个文件名一次,请定义您自己的过滤功能:

def is_image_file(filename, extensions=['.jpg', '.jpeg', '.gif', '.png']):
    return any(filename.endswith(e) for e in extensions)

for root, dirs, files in os.walk(directory):
    for filename in filter(is_image_file, files):
        pass
Run Code Online (Sandbox Code Playgroud)


use*_*312 6

这将是一个更好的方法,也许是因为您没有+重复调用并使用 atuple而不是list。

for root, dirs, files in os.walk(directory):
    for extension in ('*.jpg', '*.jpeg', '*.gif', '*.png'):
        for filename in fnmatch.filter(files, extension):
            pass
Run Code Online (Sandbox Code Playgroud)

Atuple更好,因为一旦创建了扩展,您就不会再修改它们。您只是用来迭代它们。


Chr*_*ett 6

我一直在使用它取得了很大的成功.

import fnmatch
import functools
import itertools
import os

# Remove the annotations if you're not on Python3
def find_files(dir_path: str=None, patterns: [str]=None) -> [str]:
    """
    Returns a generator yielding files matching the given patterns
    :type dir_path: str
    :type patterns: [str]
    :rtype : [str]
    :param dir_path: Directory to search for files/directories under. Defaults to current dir.
    :param patterns: Patterns of files to search for. Defaults to ["*"]. Example: ["*.json", "*.xml"]
    """
    path = dir_path or "."
    path_patterns = patterns or ["*"]

    for root_dir, dir_names, file_names in os.walk(path):
        filter_partial = functools.partial(fnmatch.filter, file_names)

        for file_name in itertools.chain(*map(filter_partial, path_patterns)):
            yield os.path.join(root_dir, file_name)
Run Code Online (Sandbox Code Playgroud)

例子:

for f in find_files(test_directory):
    print(f)
Run Code Online (Sandbox Code Playgroud)

收益率:

.\test.json
.\test.xml
.\test.ini
.\test_helpers.py
.\__init__.py
Run Code Online (Sandbox Code Playgroud)

使用多种模式进行测试

for f in find_files(test_directory, ["*.xml", "*.json", "*.ini"]):
    print(f)
Run Code Online (Sandbox Code Playgroud)

收益率:

.\test.json
.\test.xml
.\test.ini
Run Code Online (Sandbox Code Playgroud)