从python< glob中提取所有扩展

时间:2015-07-14 13:34:46

标签: python glob

Python的glob模块允许指定通配符来列出文件,并且文件非常实用。

但是如何获取/重建通配符匹配的值?

例如,假设我有这8个文件:fa1 fa2 fa3 fb1 fb3 fc1 fc2 fc3(注意:fb2丢失了。)

我能做到

import glob
glob.glob('f[ab][12]') # ['fa2', 'fb1', 'fa1']

在这种情况下,我有2个通配符:[ab][12]。它们中的每一个都匹配值ab1以及2,但这些值只有3种组合,因为一个文件fb2(一个有效的通配符组合`)不存在。

问题: 如何获取每个通配符的有效匹配值列表?更确切地说:如何获得与实际现有文件匹配的(字符串)值的元组列表?

在我的示例中,我想获取元组列表:[('a', '2'), ('b', '1'), ('a', '1')]

请注意:

  1. 我不想获取全名,只是通配符匹配的值(在我的示例中,前缀'f'不是通配符的一部分,因此我不想获得它在元组列表中);
  2. 这必须适用于所有受支持的通配符,包括*和?。
  3. 我能想到的唯一解决方案是使用正则表达式,但这基本上意味着重新实现整个glob机制来提取中间数据。

    修改

    由于我提出了一个过于宽泛的提案,因此我提出了一个非常广泛的提案。问题(???),我将问题重新表述为:是否可以使用glob / fnmatch模块获得该结果而不使用直接正则表达式?

1 个答案:

答案 0 :(得分:1)

在您的具体情况下,您可能希望使用itertools.product

import itertools
import os


def get_wildcards(*specs):
    for wildcard in itertools.product(*specs):
        if os.path.exists('f{}{}'.format(*wildcard)):
            yield wildcard


for wildcard in get_wildcards('ab', '12'):
    print wildcard

输出:

('a', '1')
('a', '2')
('b', '1')

在这种情况下,您正在使用"产品" " ab" " 12" ,最后得到4个元组,os.path.exists测试消除那些元组不要指定现有文件。

更新

计划是将文件系统通配符转换为正则表达式(您可以避免使用正则表达式,但这会很痛苦)。接下来,我们将列出当前目录中的所有文件,将每个文件与正则表达式进行匹配。如果找到匹配,我们将构造一个元组来产生它。

import re
import os


def regex_from_wildcard(wildcard):
    wildcard = wildcard.replace('.', r'\.')
    wildcard = wildcard.replace('[', '([').replace(']', '])')
    wildcard = wildcard.replace('?', r'(.)').replace('*', r'(.*)')
    wildcard = r'^{}$'.format(wildcard)
    wildcard = re.compile(wildcard)
    return wildcard


def generate_from_wildcards(wildcard):
    pattern = regex_from_wildcard(wildcard)
    for filename in os.listdir('.'):
        match_object = re.match(pattern, filename)
        if match_object:
            yield tuple(''.join(match_object.groups()))


# Test
for tup in generate_from_wildcards('f[bc]?'):
      print tup

几点说明:

  • 由于我仍然不清楚你想要什么,解决方案可能会在几个地方关闭
  • 如果通配符包含非通配符,例如f,一个点,那么这些不包含在元组中。