def iglob(dpath, pattern=None, recursive=False, with_files=True, with_dirs=True,
          maxdepth=None, exclude_dirs=[], fullpath=True, **kwargs):
    r"""
    Iteratively globs directory for pattern

    FIXME:
        This function has a speed issue

    Args:
        dpath (str):  directory path
        pattern (str):
        recursive (bool): (default = False)
        with_files (bool): (default = True)
        with_dirs (bool): (default = True)
        maxdepth (None): (default = None)
        exclude_dirs (list): (default = [])

    Yields:
        path

    References:
        http://stackoverflow.com/questions/19859840/excluding-dirs-in-os-walk
    """
    from utool import util_iter
    if kwargs.get('verbose', False):  # log what i'm going to do
        print('[util_path] glob(dpath=%r)' % truepath(dpath,))

    debug = False
    if pattern is None:
        # separate extract pattern from dpath
        if debug:
            print('[iglob] parsing dpath = %r' % (dpath,))
        dpath_ = dpath
        dpath = longest_existing_path(dpath_)
        pattern = relpath(dpath_, dpath)
    else:
        # hack check for pattern
        GLOB_PATS = ['*', '?']
        for _ in GLOB_PATS:
            assert dpath.find(_) == -1, (
                'warning: pattern _=%r in dpath, but a pattern was specified' %
                (_,))
    if isinstance(pattern, list):
        # overload pattern with list
        pattern_list  = pattern
        subiters = (
            iglob(dpath, pattern=pattern, recursive=recursive,
                  with_files=with_files, with_dirs=with_dirs,
                  maxdepth=maxdepth, exclude_dirs=exclude_dirs,
                  fullpath=fullpath, **kwargs)
            for pattern in pattern_list
        )
        for item in util_iter.iflatten(subiters):
            yield item
        raise StopIteration
    if kwargs.get('verbose', False):
        print('[iglob] pattern = %r' % (pattern,))
        print('[iglob] dpath = %r' % (dpath,))
    n_files = 0
    n_dirs  = 0
    current_depth = 0
    dpath_ = truepath(dpath)
    posx1 = len(dpath_) + len(os.path.sep)
    #exclude_dirs_rel = [relpath(dpath_, dir_) for dir_ in exclude_dirs]
    #exclude_dirs_rel = [relpath(dpath_, dir_) for dir_ in exclude_dirs]
    #print('\n\n\n')
    #import utool as ut
    #print('exclude_dirs = %s' % (ut.repr4(exclude_dirs),))
    for root, dirs, files in os.walk(dpath_, topdown=True):
        # Modifying dirs in-place will prune the subsequent files and
        # directories visitied by os.walk
        # References:
        #     http://stackoverflow.com/questions/19859840/excluding-directories-in-os-walk
        rel_root = relpath(root, dpath_)
        rel_root2 = relpath(root, dirname(dpath_))
        #print('rel_root = %r' % (rel_root,))
        #if len(dirs) > 0:
        #    print('dirs = %s' % (ut.repr4([join(rel_root, d) for d in dirs]),))
        if len(exclude_dirs) > 0:
            dirs[:] = [d for d in dirs if normpath(join(rel_root, d)) not in exclude_dirs]
            # hack
            dirs[:] = [d for d in dirs if normpath(join(rel_root2, d)) not in exclude_dirs]
            # check abs path as well
            dirs[:] = [d for d in dirs if normpath(join(root, d)) not in exclude_dirs]

        # yeild data
        # print it only if you want
        if maxdepth is not None:
            current_depth = root[posx1:].count(os.path.sep)
            if maxdepth <= current_depth:
                continue
        #print('-----------')
        #print(current_depth)
        #print(root)
        #print('==')
        #print(dirs)
        #print('-----------')
        if with_files:
            for fname in fnmatch.filter(files, pattern):
                n_files += 1
                fpath = join(root, fname)
                if fullpath:
                    yield fpath
                else:
                    yield relpath(fpath, dpath_)

        if with_dirs:
            for dname in fnmatch.filter(dirs, pattern):
                dpath = join(root, dname)
                n_dirs += 1
                if fullpath:
                    yield dpath
                else:
                    yield relpath(dpath, dpath_)
        if not recursive:
            break
    if kwargs.get('verbose', False):  # log what i've done
        n_total = n_dirs + n_files
        print('[util_path] iglob Found: %d' % (n_total))
def iglob ( dpath , pattern = None , recursive = False , with_files = True , with_dirs = True , maxdepth = None , exclude_dirs = [ ] , fullpath = True , ** kwargs ) : from utool import util_iter if kwargs . get ( 'verbose' , False ) : print ( '[util_path] glob(dpath=%r)' % truepath ( dpath , ) ) debug = False if pattern is None : if debug : print ( '[iglob] parsing dpath = %r' % ( dpath , ) ) dpath_ = dpath dpath = longest_existing_path ( dpath_ ) pattern = relpath ( dpath_ , dpath ) else : GLOB_PATS = [ '*' , '?' ] for _ in GLOB_PATS : assert dpath . find ( _ ) == - 1 , ( 'warning: pattern _=%r in dpath, but a pattern was specified' % ( _ , ) ) if isinstance ( pattern , list ) : pattern_list = pattern subiters = ( iglob ( dpath , pattern = pattern , recursive = recursive , with_files = with_files , with_dirs = with_dirs , maxdepth = maxdepth , exclude_dirs = exclude_dirs , fullpath = fullpath , ** kwargs ) for pattern in pattern_list ) for item in util_iter . iflatten ( subiters ) : yield item raise StopIteration if kwargs . get ( 'verbose' , False ) : print ( '[iglob] pattern = %r' % ( pattern , ) ) print ( '[iglob] dpath = %r' % ( dpath , ) ) n_files = 0 n_dirs = 0 current_depth = 0 dpath_ = truepath ( dpath ) posx1 = len ( dpath_ ) + len ( os . path . sep ) for root , dirs , files in os . walk ( dpath_ , topdown = True ) : rel_root = relpath ( root , dpath_ ) rel_root2 = relpath ( root , dirname ( dpath_ ) ) if len ( exclude_dirs ) > 0 : dirs [ : ] = [ d for d in dirs if normpath ( join ( rel_root , d ) ) not in exclude_dirs ] dirs [ : ] = [ d for d in dirs if normpath ( join ( rel_root2 , d ) ) not in exclude_dirs ] dirs [ : ] = [ d for d in dirs if normpath ( join ( root , d ) ) not in exclude_dirs ] if maxdepth is not None : current_depth = root [ posx1 : ] . count ( os . path . sep ) if maxdepth <= current_depth : continue if with_files : for fname in fnmatch . filter ( files , pattern ) : n_files += 1 fpath = join ( root , fname ) if fullpath : yield fpath else : yield relpath ( fpath , dpath_ ) if with_dirs : for dname in fnmatch . filter ( dirs , pattern ) : dpath = join ( root , dname ) n_dirs += 1 if fullpath : yield dpath else : yield relpath ( dpath , dpath_ ) if not recursive : break if kwargs . get ( 'verbose' , False ) : n_total = n_dirs + n_files print ( '[util_path] iglob Found: %d' % ( n_total ) )
r"""
    Iteratively globs directory for pattern

    FIXME:
        This function has a speed issue

    Args:
        dpath (str):  directory path
        pattern (str):
        recursive (bool): (default = False)
        with_files (bool): (default = True)
        with_dirs (bool): (default = True)
        maxdepth (None): (default = None)
        exclude_dirs (list): (default = [])

    Yields:
        path

    References:
        http://stackoverflow.com/questions/19859840/excluding-dirs-in-os-walk