Go Glob Case Insensitive

With Go, the filepath Glob() function is a really fast way to find all files that match a particular path, with optional wild cards. I was disappointed, though, that there is not a way to force case-insensitivity to be performed by the Glob() function to the entire pattern that is passed in.

What I found was that the Glob() function is case-insensitive on Windows and case-sensitive on Linux, due to the way that each OS handles file paths. With a regex pattern you can easily force case-insensitivity to the entire pattern using (?i), unfortunately this doesn’t work with Glob() because it doesn’t use regex patterns. Don’t give up hope, though, there is a way to do this.

The Glob() function allows the use of the ‘[‘ and ‘]’ runes to define patterns within the pattern string that is passed into the Glob() function. So the best way I found to do a case-insensitive search is to replace every Letter category Unicode code-point (aka rune) with a lowercase and uppercase version of the rune surrounded by square brackets. So ‘a’ would become ‘[aA]’ and ‘test’ would become ‘[tT][eE][sS][tT]’. In case you don’t know what is included in the Unicode Letter category, you can view the contents here. I believe that the Letter category is made up of the combination of the Ll, Lm, Lo, Lt, and Lu categories. There is no need to alter the path on Windows, since it is already case-insensitive, so I wrote a function to only be performed if the OS is not Windows.

Here is the Go code that I used to perform a conversion of a file path string into a case-insensitive version of the same file path:

func InsensitiveFilepath(path string) string {
   if runtime.GOOS == "windows" {
      return path
   }

   p := ""
   for _, r := range path {
      if unicode.IsLetter(r) {
         p += fmt.Sprintf("[%c%c]", unicode.ToLower(r), unicode.ToUpper(r))
      } else {
         p += string(r)
      }
   }
   return p
}

Here is what it looks like when it runs:

fmt.Println(InsensitiveFilepath("/home/user/test/*"))

/[hH][oO][mM][eE]/[uU][sS][eE][rR]/[tT][eE][sS][tT]/*

You can play with it yourself on the the Go playground!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s