Golang filesystem

From wikinotes
Revision as of 19:35, 30 July 2022 by Will (talk | contribs) (→‎Temporary Files/Directories)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Documentation

os (os-specific filesystem operations) https://pkg.go.dev/os@go1.18.3
path (filepaths) https://pkg.go.dev/path@go1.18.3
path/filepath (filepaths) https://pkg.go.dev/path/filepath@go1.18.3
io/ioutil (read/write) https://pkg.go.dev/io/ioutil@go1.18.3
io/fs (filesystem) https://pkg.go.dev/io/fs@go1.18.3

Errors

require "errors"
require "os"
require "io/fs"

_, err := os.Stat("foo.bar")
if errors.Is(err, fs.ErrExist) {...}
if errors.Is(err, fs.ErrNotExist) {...}
if errors.Is(err, fs.ErrPermission) {...}
if errors.Is(err, fs.ErrPermission) {...}

The old method defines Is${N} functions to test for various os package errors.


require "os"

// example filesystem operations that create errors
info, err := os.Stat("foo.bar")
fd, err := os.Create("/etc/foo")

// example error checks
if os.IsExist(err) {...}
if os.IsNotExist(err) {...}
if os.IsPermission(err) {...}

Locations

// XDG spec
dir, err := os.UserHomeDir()
dir, err := os.UserConfigDir()
dir, err := os.UserCacheDir()

Filesystem

import "os"
import "errors"

// check if file exists
if _, err := os.Stat("/var/foo.txt"); errors.Is(err, fs.ErrNotExist) {
    fmt.Println("file does not exist!")
}

dir, err := os.Getwd()
err := os.Chmod("foo.txt", 0644)
err := os.Chown("foo.txt", -1, -1)          // '-1' means do not change uid/gid
err := os.Chown("foo.txt", 1000, -1)        // set uid '1000' as owner

err := os.Link("/var/foo", "/var/bar")      // hardlink
err := os.Symlink("/var/foo", "/var/bar")   // symlink
err := os.Mkdir("/var/foo")                 // create directory (non recursively)
err := os.MkdirAll("/var/foo/bar/baz")      // creates directory (recursively)

err := os.Remove("/var/tmp/foo.bar")
err := os.RemoveAll("/var/tmp/foo")
err := os.Rename("a", "b")

Filepaths

import "path"

filename := os.ExpandEnv("${HOME}/.bashrc")    // "/home/will/.bashrc"
filename := path.Base("/home/will/.vim")       // ".vim" (basename)
filepath := path.Clean("./..//will/Downloads") // "/home/will/Downloads"
filepath := path.Join("/a/b", "c", "d")        // "/a/b/c/d"
filepath := path.Dir("/home/will/.zshrc")      // "/home/will"
filepath := path.Ext("foo.txt")                // ".txt"
isTrue := path.IsAbs("/a/b/c")                 // true
import "path/filepath"

isTrue := filepath.HasPrefix("/home/will", "/home")         // true
volume := filepath.VolumeName("//samba/share/backups/foo")  // "//samba/share"
volume := filepath.VolumeName("C://Users")                  // "C://"

walk filesystem (one file at a time) using visitor pattern

import "path/filepath"

filepath.WalkDir("/home/foo", func(path string, info fs.FileInfo, err error) error {
    if err != nil {
        return err
    }

    fmt.Printf(path)
    return nil
})

Files

For more details, see golang input/output

import "os"

file, err := os.Create("foo.txt")  // create/replace open for writing
file, err := os.Open("foo.txt")    // open for reading

bytes_w, err := file.Write([]byte("abc"))
bytes_w, err := file.WriteString("abc")

fileinfo, err := file.Stat()

Dirty one-off reads/writes for small files

require "os"

os.WriteFile("/var/tmp/foo.txt", []byte("abc"), 0644)

conts, err := os.ReadFile("/var/tmp/foo.txt")

Temporary Files/Directories

Temporary Directories

// creates tempdir,
// '*' in filename is placement of random str
// you must delete!
path, err := os.MkdirTemp("/var/tmp", "cache-*")
defer os.RemoveAll(path)

Temporary Files (see golang afero)

// go doesn't ship with tempfiles, but 'afero' does
Fs := afero.NewOsFs()
Os := afero.Afero{Fs: Fs}
Os.TempFile(os.Tempdir(), "my-prefix-*")