簡體   English   中英

使用 fnmatch.filter 通過多個可能的文件擴展名過濾文件

[英]Use fnmatch.filter to filter files by more than one possible file extension

鑒於以下一段python代碼:

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

如何篩選多個擴展名? 在這種特殊情況下,我想獲取所有以 *.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

但我認為它不是很優雅和高性能。

有人有更好的主意嗎?

如果您只需要檢查擴展名(即沒有更多的通配符),為什么不簡單地使用基本的字符串操作呢?

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

我認為你的代碼實際上很好。 如果您只想觸摸每個文件名一次,請定義您自己的過濾功能:

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

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

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)

例子:

for f in find_files(test_directory):
    print(f)

產量:

.\test.json
.\test.xml
.\test.ini
.\test_helpers.py
.\__init__.py

使用多種模式進行測試:

for f in find_files(test_directory, ["*.xml", "*.json", "*.ini"]):
    print(f)

產量:

.\test.json
.\test.xml
.\test.ini

這也不是很優雅,但它有效:

for root, dirs, files in os.walk(directory):
    for filename in fnmatch.filter(files, '*.png') + fnmatch.filter(files, '*.jpg') + fnmatch.filter(files, '*.jpeg') + fnmatch.filter(files, '*.gif'):
        pass

這將是一個更好的方法,也許是因為您沒有重復調用+並使用tuple而不是list

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

tuple更好,因為一旦創建了擴展,您就不會修改它們。 你只是用來迭代它們。

請試試這個:

# pattern_list = ['*.jpg', '__.*']
def checkFilepatter(filename, pattern_list):
    for pattern in pattern_list:
        if fnmatch.fnmatch(filename, pattern):
            return True
    return False

這是我用來過濾 apache 日志目錄中文件的內容。 在這里我排除了錯誤

rep_filters = [now.strftime("%Y%m%d")]
def files_filter(liste_fic, filters = rep_filters):
    s = "(fic for fic in liste_fic if fic.find('error') < 0"
    for filter in filters:
        s += " and fic.find('%s') >=0 " % filter
    s += ")"
    return eval(s)

您可以使用列表理解來檢查my_filepatterns定義的任何文件掩碼匹配:

import fnmatch

my_file = 'my_precious.txt'
patterns = ('*.txt', '*.html', '*.mp3')


if [pat for pat in patterns if fnmatch.fnmatch(my_file, pat)]:
    print('We have a match!')
else:
    print('No match')

在內部, fnmatch用戶正則表達式。 還有一種方法可以從 fnmatch 模式生成正則表達式 - fnmatch.translate 這也可能會帶來一點加速。

import fnmatch
import os
import re

image_exts = ['jpg', 'jpeg', 'gif', 'png']
image_re = re.compile('|'.join(fnmatch.translate('*.' + e) for e in image_exts))
for root, dirs, files in os.walk(directory):
    for filename in files:
        if image_re.match(filename):
            ...

最明確的解決辦法是:

import os

for root, dirs, files in os.walk(directory):
    for filename in files:
        _, ext = os.path.splitext(filename)
        if ext in ['.jpg', '.jpeg', '.gif', '.png']:
            ...

或者,使用pathlib

for path in pathlib.Path(directory).glob('**/*'):
    if path.suffix in ['.jpg', '.jpeg', '.gif', '.png']:
        ...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM