Home | History | Annotate | Download | only in python2.7
      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     if not has_magic(pathname):
     39         if os.path.lexists(pathname):
     40             yield pathname
     41         return
     42     dirname, basename = os.path.split(pathname)
     43     if not dirname:
     44         for name in glob1(os.curdir, basename):
     45             yield name
     46         return
     47     # `os.path.split()` returns the argument itself as a dirname if it is a
     48     # drive or UNC path.  Prevent an infinite recursion if a drive or UNC path
     49     # contains magic characters (i.e. r'\\?\C:').
     50     if dirname != pathname and has_magic(dirname):
     51         dirs = iglob(dirname)
     52     else:
     53         dirs = [dirname]
     54     if has_magic(basename):
     55         glob_in_dir = glob1
     56     else:
     57         glob_in_dir = glob0
     58     for dirname in dirs:
     59         for name in glob_in_dir(dirname, basename):
     60             yield os.path.join(dirname, name)
     61 
     62 # These 2 helper functions non-recursively glob inside a literal directory.
     63 # They return a list of basenames. `glob1` accepts a pattern while `glob0`
     64 # takes a literal basename (so it only has to check for its existence).
     65 
     66 def glob1(dirname, pattern):
     67     if not dirname:
     68         dirname = os.curdir
     69     if isinstance(pattern, _unicode) and not isinstance(dirname, unicode):
     70         dirname = unicode(dirname, sys.getfilesystemencoding() or
     71                                    sys.getdefaultencoding())
     72     try:
     73         names = os.listdir(dirname)
     74     except os.error:
     75         return []
     76     if pattern[0] != '.':
     77         names = filter(lambda x: x[0] != '.', names)
     78     return fnmatch.filter(names, pattern)
     79 
     80 def glob0(dirname, basename):
     81     if basename == '':
     82         # `os.path.split()` returns an empty basename for paths ending with a
     83         # directory separator.  'q*x/' should match only directories.
     84         if os.path.isdir(dirname):
     85             return [basename]
     86     else:
     87         if os.path.lexists(os.path.join(dirname, basename)):
     88             return [basename]
     89     return []
     90 
     91 
     92 magic_check = re.compile('[*?[]')
     93 
     94 def has_magic(s):
     95     return magic_check.search(s) is not None
     96