mirror of
				https://github.com/python/cpython.git
				synced 2025-11-04 11:49:12 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			107 lines
		
	
	
	
		
			2.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			107 lines
		
	
	
	
		
			2.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
"""Filename matching with shell patterns.
 | 
						|
 | 
						|
fnmatch(FILENAME, PATTERN) matches according to the local convention.
 | 
						|
fnmatchcase(FILENAME, PATTERN) always takes case in account.
 | 
						|
 | 
						|
The functions operate by translating the pattern into a regular
 | 
						|
expression.  They cache the compiled regular expressions for speed.
 | 
						|
 | 
						|
The function translate(PATTERN) returns a regular expression
 | 
						|
corresponding to PATTERN.  (It does not compile it.)
 | 
						|
"""
 | 
						|
 | 
						|
import re
 | 
						|
 | 
						|
__all__ = ["fnmatch","fnmatchcase","translate"]
 | 
						|
 | 
						|
_cache = {}
 | 
						|
 | 
						|
def fnmatch(name, pat):
 | 
						|
    """Test whether FILENAME matches PATTERN.
 | 
						|
 | 
						|
    Patterns are Unix shell style:
 | 
						|
 | 
						|
    *       matches everything
 | 
						|
    ?       matches any single character
 | 
						|
    [seq]   matches any character in seq
 | 
						|
    [!seq]  matches any char not in seq
 | 
						|
 | 
						|
    An initial period in FILENAME is not special.
 | 
						|
    Both FILENAME and PATTERN are first case-normalized
 | 
						|
    if the operating system requires it.
 | 
						|
    If you don't want this, use fnmatchcase(FILENAME, PATTERN).
 | 
						|
    """
 | 
						|
 | 
						|
    import os
 | 
						|
    name = os.path.normcase(name)
 | 
						|
    pat = os.path.normcase(pat)
 | 
						|
    return fnmatchcase(name, pat)
 | 
						|
 | 
						|
def filter(names, pat):
 | 
						|
    """Return the subset of the list NAMES that match PAT"""
 | 
						|
    import os,posixpath
 | 
						|
    result=[]
 | 
						|
    pat=os.path.normcase(pat)
 | 
						|
    if not pat in _cache:
 | 
						|
        res = translate(pat)
 | 
						|
        _cache[pat] = re.compile(res)
 | 
						|
    match=_cache[pat].match
 | 
						|
    if os.path is posixpath:
 | 
						|
        # normcase on posix is NOP. Optimize it away from the loop.
 | 
						|
        for name in names:
 | 
						|
            if match(name):
 | 
						|
                result.append(name)
 | 
						|
    else:
 | 
						|
        for name in names:
 | 
						|
            if match(os.path.normcase(name)):
 | 
						|
                result.append(name)
 | 
						|
    return result
 | 
						|
 | 
						|
def fnmatchcase(name, pat):
 | 
						|
    """Test whether FILENAME matches PATTERN, including case.
 | 
						|
 | 
						|
    This is a version of fnmatch() which doesn't case-normalize
 | 
						|
    its arguments.
 | 
						|
    """
 | 
						|
 | 
						|
    if not pat in _cache:
 | 
						|
        res = translate(pat)
 | 
						|
        _cache[pat] = re.compile(res)
 | 
						|
    return _cache[pat].match(name) is not None
 | 
						|
 | 
						|
def translate(pat):
 | 
						|
    """Translate a shell PATTERN to a regular expression.
 | 
						|
 | 
						|
    There is no way to quote meta-characters.
 | 
						|
    """
 | 
						|
 | 
						|
    i, n = 0, len(pat)
 | 
						|
    res = ''
 | 
						|
    while i < n:
 | 
						|
        c = pat[i]
 | 
						|
        i = i+1
 | 
						|
        if c == '*':
 | 
						|
            res = res + '.*'
 | 
						|
        elif c == '?':
 | 
						|
            res = res + '.'
 | 
						|
        elif c == '[':
 | 
						|
            j = i
 | 
						|
            if j < n and pat[j] == '!':
 | 
						|
                j = j+1
 | 
						|
            if j < n and pat[j] == ']':
 | 
						|
                j = j+1
 | 
						|
            while j < n and pat[j] != ']':
 | 
						|
                j = j+1
 | 
						|
            if j >= n:
 | 
						|
                res = res + '\\['
 | 
						|
            else:
 | 
						|
                stuff = pat[i:j].replace('\\','\\\\')
 | 
						|
                i = j+1
 | 
						|
                if stuff[0] == '!':
 | 
						|
                    stuff = '^' + stuff[1:]
 | 
						|
                elif stuff[0] == '^':
 | 
						|
                    stuff = '\\' + stuff
 | 
						|
                res = '%s[%s]' % (res, stuff)
 | 
						|
        else:
 | 
						|
            res = res + re.escape(c)
 | 
						|
    return res + "$"
 |