How to create a directory if it does not exist in Go

Creating a directory in Go can be done through the os.Mkdir method in the standard library. However, if you try to create a directory that already exists, you will get a PathError notifying you of the problem. This short article will help you solve the problem of selectively creating a directory if it does not exist in Go

path := "sample"
// ignore the error
_ = os.Mkdir(path, os.ModePerm)

Ignoring the error from os.Mkdir() (as shown above) can be an acceptable solution since the error just reports that the directory already exists. However, ignoring errors is generally frowned upon so it’s better to handle this possibility in a proper manner. There are two main ways to solve this problem depending on what you’re trying to achieve.

1. Check for the directory’s existence first

The first method involves checking to see if the directory exists first before attempting to create it. This is a straightforward process in Go:

package main

import (
	"errors"
	"log"
	"os"
)

func main() {
	path := "sample"
	if _, err := os.Stat(path); errors.Is(err, os.ErrNotExist) {
		err := os.Mkdir(path, os.ModePerm)
		if err != nil {
			log.Println(err)
		}
	}
}

The os.Stat() method is used to get information about a given path. The error from os.Stat() is compared with os.ErrNotExist using the Is() method from the errors package to see if it reports that the directory represented by path does not exist. You might see older code use the os.IsNotExist() method for this comparison but this is the modern way for Go 1.13 and later. If the error from os.Stat() is nil (which means the path exists), the comparison will fail and the contents of the outermost if block will not be executed.

2. Recursively create all directories

A second way to solve this problem involves the use of the os.MkdirAll() method which is handy if you want to create several directories recursively including any missing parents. Unlike os.Mkdir, it does not return an error of any if the directories in the path already exists. This means you can safely use this method without having checks for whether a directory in the path exists or not.

package main

import (
	"log"
	"os"
)

func main() {
	path := "sample/deeply/nested/directory"
	err := os.MkdirAll(path, os.ModePerm)
	if err != nil {
		log.Println(err)
	}
}

When using os.MkdirAll() you may encounter an error if the path exists but is not a directory. Otherwise, you won’t encounter any errors as already existing directory paths are left alone without any modifications.


Thanks for reading, and happy coding!