1 | """Filename globbing utility.""" |
---|
2 | |
---|
3 | import sys |
---|
4 | import os |
---|
5 | import re |
---|
6 | import fnmatch |
---|
7 | |
---|
8 | try: |
---|
9 | _unicode = unicode |
---|
10 | except NameError: |
---|
11 | # If Python is built without Unicode support, the unicode type |
---|
12 | # will not exist. Fake one. |
---|
13 | class _unicode(object): |
---|
14 | pass |
---|
15 | |
---|
16 | __all__ = ["glob", "iglob"] |
---|
17 | |
---|
18 | def glob(pathname): |
---|
19 | """Return a list of paths matching a pathname pattern. |
---|
20 | |
---|
21 | The pattern may contain simple shell-style wildcards a la |
---|
22 | fnmatch. However, unlike fnmatch, filenames starting with a |
---|
23 | dot are special cases that are not matched by '*' and '?' |
---|
24 | patterns. |
---|
25 | |
---|
26 | """ |
---|
27 | return list(iglob(pathname)) |
---|
28 | |
---|
29 | def iglob(pathname): |
---|
30 | """Return an iterator which yields the paths matching a pathname pattern. |
---|
31 | |
---|
32 | The pattern may contain simple shell-style wildcards a la |
---|
33 | fnmatch. However, unlike fnmatch, filenames starting with a |
---|
34 | dot are special cases that are not matched by '*' and '?' |
---|
35 | patterns. |
---|
36 | |
---|
37 | """ |
---|
38 | dirname, basename = os.path.split(pathname) |
---|
39 | if not has_magic(pathname): |
---|
40 | if basename: |
---|
41 | if os.path.lexists(pathname): |
---|
42 | yield pathname |
---|
43 | else: |
---|
44 | # Patterns ending with a slash should match only directories |
---|
45 | if os.path.isdir(dirname): |
---|
46 | yield pathname |
---|
47 | return |
---|
48 | if not dirname: |
---|
49 | for name in glob1(os.curdir, basename): |
---|
50 | yield name |
---|
51 | return |
---|
52 | # `os.path.split()` returns the argument itself as a dirname if it is a |
---|
53 | # drive or UNC path. Prevent an infinite recursion if a drive or UNC path |
---|
54 | # contains magic characters (i.e. r'\\?\C:'). |
---|
55 | if dirname != pathname and has_magic(dirname): |
---|
56 | dirs = iglob(dirname) |
---|
57 | else: |
---|
58 | dirs = [dirname] |
---|
59 | if has_magic(basename): |
---|
60 | glob_in_dir = glob1 |
---|
61 | else: |
---|
62 | glob_in_dir = glob0 |
---|
63 | for dirname in dirs: |
---|
64 | for name in glob_in_dir(dirname, basename): |
---|
65 | yield os.path.join(dirname, name) |
---|
66 | |
---|
67 | # These 2 helper functions non-recursively glob inside a literal directory. |
---|
68 | # They return a list of basenames. `glob1` accepts a pattern while `glob0` |
---|
69 | # takes a literal basename (so it only has to check for its existence). |
---|
70 | |
---|
71 | def glob1(dirname, pattern): |
---|
72 | if not dirname: |
---|
73 | dirname = os.curdir |
---|
74 | if isinstance(pattern, _unicode) and not isinstance(dirname, unicode): |
---|
75 | dirname = unicode(dirname, sys.getfilesystemencoding() or |
---|
76 | sys.getdefaultencoding()) |
---|
77 | try: |
---|
78 | names = os.listdir(dirname) |
---|
79 | except os.error: |
---|
80 | return [] |
---|
81 | if pattern[0] != '.': |
---|
82 | names = filter(lambda x: x[0] != '.', names) |
---|
83 | return fnmatch.filter(names, pattern) |
---|
84 | |
---|
85 | def glob0(dirname, basename): |
---|
86 | if basename == '': |
---|
87 | # `os.path.split()` returns an empty basename for paths ending with a |
---|
88 | # directory separator. 'q*x/' should match only directories. |
---|
89 | if os.path.isdir(dirname): |
---|
90 | return [basename] |
---|
91 | else: |
---|
92 | if os.path.lexists(os.path.join(dirname, basename)): |
---|
93 | return [basename] |
---|
94 | return [] |
---|
95 | |
---|
96 | |
---|
97 | magic_check = re.compile('[*?[]') |
---|
98 | |
---|
99 | def has_magic(s): |
---|
100 | return magic_check.search(s) is not None |
---|