blob: 9b31856546f5d763f91ed9434648ffb40a97cfef [file] [log] [blame]
Guido van Rossum7e4b2de1995-01-27 02:41:45 +00001"""Filename matching with shell patterns.
Guido van Rossum05e52191992-01-12 23:29:29 +00002
Guido van Rossum7e4b2de1995-01-27 02:41:45 +00003fnmatch(FILENAME, PATTERN) matches according to the local convention.
4fnmatchcase(FILENAME, PATTERN) always takes case in account.
Guido van Rossum05e52191992-01-12 23:29:29 +00005
Guido van Rossum7e4b2de1995-01-27 02:41:45 +00006The functions operate by translating the pattern into a regular
7expression. They cache the compiled regular expressions for speed.
8
9The function translate(PATTERN) returns a regular expression
10corresponding to PATTERN. (It does not compile it.)
11"""
12
13_cache = {}
Guido van Rossum762c39e1991-01-01 18:11:14 +000014
Guido van Rossum762c39e1991-01-01 18:11:14 +000015def fnmatch(name, pat):
Guido van Rossum7e4b2de1995-01-27 02:41:45 +000016 """Test whether FILENAME matches PATTERN.
17
18 Patterns are Unix shell style:
19
20 * matches everything
21 ? matches any single character
22 [seq] matches any character in seq
23 [!seq] matches any char not in seq
24
25 An initial period in FILENAME is not special.
26 Both FILENAME and PATTERN are first case-normalized
27 if the operating system requires it.
28 If you don't want this, use fnmatchcase(FILENAME, PATTERN).
29 """
30
31 import os
Guido van Rossum05e52191992-01-12 23:29:29 +000032 name = os.path.normcase(name)
33 pat = os.path.normcase(pat)
Guido van Rossum7e4b2de1995-01-27 02:41:45 +000034 return fnmatchcase(name, pat)
35
36def fnmatchcase(name, pat):
37 """Test wheter FILENAME matches PATTERN, including case.
38
39 This is a version of fnmatch() which doesn't case-normalize
40 its arguments.
41 """
42
43 if not _cache.has_key(pat):
Guido van Rossum05e52191992-01-12 23:29:29 +000044 res = translate(pat)
Guido van Rossum7e4b2de1995-01-27 02:41:45 +000045 import regex
Guido van Rossum05e52191992-01-12 23:29:29 +000046 save_syntax = regex.set_syntax(0)
Guido van Rossum7e4b2de1995-01-27 02:41:45 +000047 _cache[pat] = regex.compile(res)
Guido van Rossum05e52191992-01-12 23:29:29 +000048 save_syntax = regex.set_syntax(save_syntax)
Guido van Rossum7e4b2de1995-01-27 02:41:45 +000049 return _cache[pat].match(name) == len(name)
Guido van Rossum762c39e1991-01-01 18:11:14 +000050
Guido van Rossum05e52191992-01-12 23:29:29 +000051def translate(pat):
Guido van Rossum7e4b2de1995-01-27 02:41:45 +000052 """Translate a shell PATTERN to a regular expression.
53
54 There is no way to quote meta-characters.
55 """
56
Guido van Rossumbdfcfcc1992-01-01 19:35:13 +000057 i, n = 0, len(pat)
Guido van Rossum05e52191992-01-12 23:29:29 +000058 res = ''
Guido van Rossumbdfcfcc1992-01-01 19:35:13 +000059 while i < n:
Guido van Rossum762c39e1991-01-01 18:11:14 +000060 c = pat[i]
Guido van Rossumbdfcfcc1992-01-01 19:35:13 +000061 i = i+1
Guido van Rossum05e52191992-01-12 23:29:29 +000062 if c == '*':
63 res = res + '.*'
64 elif c == '?':
65 res = res + '.'
66 elif c == '[':
67 j = i
68 if j < n and pat[j] == '!':
69 j = j+1
70 if j < n and pat[j] == ']':
71 j = j+1
72 while j < n and pat[j] != ']':
73 j = j+1
74 if j >= n:
75 res = res + '\\['
76 else:
77 stuff = pat[i:j]
78 i = j+1
79 if stuff[0] == '!':
80 stuff = '[^' + stuff[1:] + ']'
81 elif stuff == '^'*len(stuff):
82 stuff = '\\^'
83 else:
84 while stuff[0] == '^':
85 stuff = stuff[1:] + stuff[0]
86 stuff = '[' + stuff + ']'
87 res = res + stuff
88 elif c in '\\.+^$':
89 res = res + ('\\' + c)
90 else:
91 res = res + c
Guido van Rossum762c39e1991-01-01 18:11:14 +000092 return res