Create Nested Directories in Go (os.Mkdir, os.MkdirAll, mkdir -p)

Create nested directories in Go with os.Mkdir per level, os.MkdirAll for a full path in one call, filepath.Join for portable paths, optional os.Stat guards, or exec.Command mkdir -p when shell semantics are acceptable.

Published

Updated

Read time 2 min read

Reviewed byDeepak Prasad

Create Nested Directories in Go (os.Mkdir, os.MkdirAll, mkdir -p)

You golang create nested directory trees either level by level with os.Mkdir, or in one step with os.MkdirAll, which creates parent components as needed and succeeds if the path already exists. Combine with filepath.Join for portable paths. Shell-style mkdir -p is available through os/exec when that is clearer for your deployment.

Tested with Go 1.24 on Linux.


os.Mkdir one level at a time

Each call creates a single directory; the parent must exist, and repeating the program fails if the directory is already there unless you check first.

go
package main

import (
	"fmt"
	"os"
)

func main() {
	myDir := "/tmp/glc-topdir"
	if err := os.Mkdir(myDir, 0o755); err != nil && !os.IsExist(err) {
		panic(err)
	}
	if err := os.Mkdir(myDir+"/subdir1", 0o755); err != nil && !os.IsExist(err) {
		panic(err)
	}
	if err := os.Mkdir(myDir+"/subdir2", 0o755); err != nil && !os.IsExist(err) {
		panic(err)
	}
	fmt.Println("ok")
}

Use os.IsExist or errors.Is(err, fs.ErrExist) when you intentionally allow reruns.


go
package main

import (
	"fmt"
	"os"
	"path/filepath"
)

func main() {
	p := filepath.Join("/tmp", "glc-mkdirall", "a", "b", "c")
	if err := os.MkdirAll(p, 0o755); err != nil {
		panic(err)
	}
	fi, err := os.Stat(p)
	if err != nil {
		panic(err)
	}
	fmt.Println(fi.IsDir())
}
Output

You should see true.


Helper that skips if the leaf already exists

go
package main

import (
	"fmt"
	"os"
	"path/filepath"
)

func ensureDir(path string) error {
	_, err := os.Stat(path)
	if err == nil {
		fmt.Println("already exists:", path)
		return nil
	}
	if !os.IsNotExist(err) {
		return err
	}
	if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
		return err
	}
	return os.Mkdir(path, 0o755)
}

func main() {
	path := filepath.Join("/tmp", "glc-ensure", "subdir1", "subdir2")
	if err := ensureDir(path); err != nil {
		panic(err)
	}
	fmt.Println("created or skipped:", path)
}
Output

You should see a created or skipped message and the final path printed.


Shell: mkdir -p via os/exec

go
package main

import (
	"fmt"
	"os/exec"
)

func main() {
	path := "/tmp/glc-exec/a/b/c"
	cmd := exec.Command("mkdir", "-p", path)
	if err := cmd.Run(); err != nil {
		panic(err)
	}
	fmt.Println("ok")
}

Prefer os.MkdirAll when you do not need shell features; use exec when mirroring scripts or invoking platform tools (exec in Go).


Summary

For golang create nested directory workflows, os.MkdirAll with filepath.Join is the standard library sweet spot: idempotent for existing paths, one call for the whole tree, and no shell dependency. Use layered Mkdir plus Stat only when you need stricter control, and exec.Command("mkdir","-p",path) when shell parity matters.


References


Frequently Asked Questions

1. What is the usual way to create nested directories in Go?

Prefer os.MkdirAll(path, perm) so parents are created and existing directories are not an error.

2. When should I use os.Mkdir instead of MkdirAll?

Use Mkdir for a single new directory when the parent must already exist; repeat for each level or combine with Stat if you are mirroring legacy shell scripts.

3. How do I build nested paths portably?

Use filepath.Join rather than hard-coded slashes, especially when targeting Windows as well as Linux.

4. How can I run mkdir -p from Go?

Use os/exec with mkdir and -p; validate paths and remember this shells out to the platform mkdir binary instead of using only the standard library.

5. What permission bits should I pass?

Use os.FileMode literals such as 0o755 for common directory permissions; avoid world-writable modes unless you intend them.
Deepak Prasad

R&D Engineer

Founder of GoLinuxCloud with more than 15 years of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive …