""" Filename globbing like the python glob module with minor differences: * glob relative to an arbitrary directory * include . and .. * check that link targets exist, not just links """ import os, re, fnmatch import util _globcheck = re.compile('[[*?]') def hasglob(p): return _globcheck.search(p) is not None def glob(fsdir, path): """ Yield paths matching the path glob. Sorts as a bonus. Excludes '.' and '..' """ dir, leaf = os.path.split(path) if dir == '': return globpattern(fsdir, leaf) if hasglob(dir): dirsfound = glob(fsdir, dir) else: dirsfound = [dir] r = [] for dir in dirsfound: fspath = util.normaljoin(fsdir, dir) if not os.path.isdir(fspath): continue r.extend((util.normaljoin(dir, found) for found in globpattern(fspath, leaf))) return r def globpattern(dir, pattern): """ Return leaf names in the specified directory which match the pattern. """ if not hasglob(pattern): if pattern == '': if os.path.isdir(dir): return [''] return [] if os.path.exists(util.normaljoin(dir, pattern)): return [pattern] return [] leaves = os.listdir(dir) + ['.', '..'] # "hidden" filenames are a bit special if not pattern.startswith('.'): leaves = [leaf for leaf in leaves if not leaf.startswith('.')] leaves = fnmatch.filter(leaves, pattern) leaves = filter(lambda l: os.path.exists(util.normaljoin(dir, l)), leaves) leaves.sort() return leaves