def inis2dict(ini_paths: Union[str, Sequence[str]]) -> dict:
    """
    Take one or more ini files and return a dict with configuration from all,
    interpolating bash-style variables ${VAR} or ${VAR:-DEFAULT}.

    :param ini_paths: path or paths to .ini files
    """

    var_dflt = r'\${(.*?):-(.*?)}'
    def _interpolate(content):
        rv = expandvars(content)
        while True:
            match = re.search(var_dflt, rv)
            if match is None:
                break
            bash_var = '${{{}}}'.format(match.group(1))
            value = expandvars(bash_var)
            rv = re.sub(var_dflt, match.group(2) if value == bash_var else value, rv, count=1)

        return rv

    parser = ConfigParser()

    for ini in [ini_paths] if isinstance(ini_paths, str) else ini_paths:
        if not isfile(ini):
            raise FileNotFoundError('No such file: {}'.format(ini))
        with open(ini, 'r') as ini_fh:
            ini_text = _interpolate(ini_fh.read())
            parser.read_string(ini_text)

    return {s: dict(parser[s].items()) for s in parser.sections()}