How to create a hidden file in Windows, macOS and Linux (Go)

Hidden files and directories are commonly used for storing user preferences or preserving the state of a utility. Creating a hidden file or directory is easy to do in Go, but there are differences in how it’s done on Linux/macOS compared to Windows.

To create a hidden file or directory in Linux and macOS, all you need to do is prepend the dot (.) character to the filename as shown below:

// +build !windows

package main

import (
	"log"
	"os"
	"strings"
)

func main() {
	filename := "config"
	if !strings.HasPrefix(filename, ".") {
		filename = "." + filename
	}

	err := os.WriteFile(filename, []byte(filename), 0666)
	if err != nil {
		log.Fatal(err)
	}
}

If the filename does not start with a ., the dot character is prepended to it and os.WriteFile() is used to create the file accordingly.

On Windows, prefixing a filename with the dot character does not make it a hidden file. You have to set the Hidden attribute on the file before it is recognised as a hidden file by the operating system. Here’s how to do it:

// +build windows

package main

import (
	"log"
	"os"
	"syscall"
)

func setHidden(path string) error {
	filenameW, err := syscall.UTF16PtrFromString(path)
	if err != nil {
		return err
	}

	err = syscall.SetFileAttributes(filenameW, syscall.FILE_ATTRIBUTE_HIDDEN)
	if err != nil {
		return err
	}

	return nil
}

func main() {
	filename := "config"
	err := os.WriteFile(filename, []byte(filename), 0666)
	if err != nil {
		log.Fatal(err)
	}

	err = setHidden(filename)
	if err != nil {
		log.Fatal(err)
	}
}

In this case, the Hidden attribute is set on the file after creation through the syscall package. If you want to know how to detect hidden files or directories in Go, check out this snippet.

Thanks for reading, and happy coding!