Search code examples
goglob

Is there no way to list directories only using Golang Glob?


Golang Glob doesn't behave the way I expected it to. Let's say I have a directory "foo" with the following structure:

foo
|-- 1.txt
|-- 2.csv
|-- 3.json
|-- bar
`-- baz

I want to do a glob that gets only the directories "bar" and "baz" within foo. So I try this:

path = "foo/*/"
matches, err := filepath.Glob(path)
if err != nil {
    log.Fatal(err)
}
fmt.Println(matches)

This produces no matches:

[]

If I remove the last trailing slash and change path to "foo/*", I get both files and directories, which is not the result I want:

[foo/1.txt foo/2.csv foo/3.json foo/bar foo/baz]

I would expect that if a trailing slash is present, Glob would return only directories that match the glob pattern. I see that the same issue is noted on GitHub, but couldn't see any workaround for it - it sounds either like a bug, a poorly documented feature, or simply a lack of an expected feature.

I've checked the Go docs for the Match function, which Glob uses, and it doesn't mention anything about a trailing slash.

So basically: is there a workaround so that I can glob only directories under a certain path using Glob, or do I need to use another method for this task?


Solution

  • You can iterate through the list of matches and call os.Stat on each of them. os.Stat returns a FileInfo structure describing the file and it includes a method called IsDir for checking if a file is a directory. Sample code:

    // Note: Ignoring errors.
    matches, _ := filepath.Glob("foo/*")
    var dirs []string
    for _, match := range matches {
        f, _ := os.Stat(match)
        if f.IsDir() {
            dirs = append(dirs, match)
        }
    }