Directories
os.Mkdir, os.MkdirAll, os.ReadDir, os.Remove, os.RemoveAll, os.Getwd, and os.Chdir for directory operations.
The os package provides functions for creating, listing, and removing directories. Most operations mirror the familiar Unix commands but are portable across operating systems.
os.Mkdir creates a single directory. It fails if the path already exists or if any intermediate directory is missing. os.MkdirAll creates the full path including all intermediate directories, and is idempotent - it returns nil if the directory already exists.
package main
import (
"fmt"
"os"
)
func main() {
// Create a single directory - fails if parent doesn't exist
err := os.Mkdir("subdir", 0755)
if err != nil {
panic(err)
}
// Create a full path - idempotent, no error if already exists
err = os.MkdirAll("a/b/c", 0755)
if err != nil {
panic(err)
}
fmt.Println("directories created")
}os.ReadDir lists the entries in a directory, sorted by name. Each fs.DirEntry provides the name, type (file or directory), and - via Info() - the full fs.FileInfo.
package main
import (
"fmt"
"os"
)
func main() {
entries, err := os.ReadDir(".")
if err != nil {
panic(err)
}
for _, e := range entries {
kind := "file"
if e.IsDir() {
kind = "dir "
}
fmt.Printf("%s %s\n", kind, e.Name())
}
}os.Remove deletes a single file or empty directory. os.RemoveAll deletes a path and everything under it - equivalent to rm -rf. os.Getwd returns the current working directory; os.Chdir changes it.
package main
import (
"fmt"
"os"
)
func main() {
os.MkdirAll("tmp/nested", 0755)
// Remove a single empty directory
os.Remove("tmp/nested")
// Remove a directory tree (rm -rf equivalent)
os.RemoveAll("tmp")
wd, err := os.Getwd()
if err != nil {
panic(err)
}
fmt.Println("working dir:", wd)
}In production
os.RemoveAll is equivalent to rm -rf - no confirmation, no recycle bin, no undo. In production code, validate that the path is inside a known prefix (using filepath.Abs and strings.HasPrefix) before calling it; a bug that constructs a wrong path can delete critical data. os.MkdirAll is idempotent - prefer it over a stat-then-mkdir sequence, which has a TOCTOU race. os.ReadDir is the modern replacement for ioutil.ReadDir (deprecated) and is faster because it uses the fs.DirEntry type that avoids a stat call per entry when only the name and type are needed. For recursive traversal, use filepath.WalkDir rather than calling os.ReadDir recursively - it handles errors consistently and lets you skip subtrees by returning fs.SkipDir. Avoid os.Chdir in server code - it changes the working directory for the whole process, not just the current goroutine.
Enjoyed this? Get more essays on software craft delivered to your inbox.
Subscribe free