code: func (b *Builder) ReadPath(path string) ([]Source, error) {
  	f, err := os.Open(path)
  	if err != nil {
  		return nil, fmt.Errorf("config: Open failed on %s. %s", path, err)
  	}
  	defer f.Close()
  
  	fi, err := f.Stat()
  	if err != nil {
  		return nil, fmt.Errorf("config: Stat failed on %s. %s", path, err)
  	}
  
  	if !fi.IsDir() {
  		src, err := b.ReadFile(path)
  		if err != nil {
  			return nil, err
  		}
  		return []Source{src}, nil
  	}
  
  	fis, err := f.Readdir(-1)
  	if err != nil {
  		return nil, fmt.Errorf("config: Readdir failed on %s. %s", path, err)
  	}
  
  	// sort files by name
  	sort.Sort(byName(fis))
  
  	var sources []Source
  	for _, fi := range fis {
  		fp := filepath.Join(path, fi.Name())
  		// check for a symlink and resolve the path
  		if fi.Mode()&os.ModeSymlink > 0 {
  			var err error
  			fp, err = filepath.EvalSymlinks(fp)
  			if err != nil {
  				return nil, err
  			}
  			fi, err = os.Stat(fp)
  			if err != nil {
  				return nil, err
  			}
  		}
  		// do not recurse into sub dirs
  		if fi.IsDir() {
  			continue
  		}
  
  		if b.shouldParseFile(fp) {
  			src, err := b.ReadFile(fp)
  			if err != nil {
  				return nil, err
  			}
  			sources = append(sources, src)
  		}
  	}
  	return sources, nil
  }
docs: // ReadPath reads a single config file or all files in a directory (but
  // not its sub-directories) and appends them to the list of config
  // sources.