Skip to the content.

Perform operations on files and directories

Things you likely want to do to files and directories are moving them about, removing them, rename them etc. In short, high-level operations that is less about the content of the file but doing something with it.

Introduction

In this chapter you will:

File information

You might want to look at a specific file and find out various details about it. Things that can be interesting are:

To get file information, use the Stat() function like so:

fileStat, err := os.Stat(path)
fmt.Println("File Name:", fileStat.Name())        // Base name of the file
fmt.Println("Size:", fileStat.Size())             // Length in bytes for regular files
fmt.Println("Permissions:", fileStat.Mode())      // File mode bits
fmt.Println("Last Modified:", fileStat.ModTime()) // Last modification time
fmt.Println("Is Directory: ", fileStat.IsDir())   // Abbreviation for Mode().IsDir()

Also when you call ReadDir() you get back an array of FileInfo objects:

files, err := ioutil.ReadDir(path)

Copy file

Copying a file is really three operations:

Here’s how you can implement a copy operation:

// copies 'test.txt' and its content to 'copy.txt'
src := "test.txt"
dest := "copy.txt"

srcFile, err := os.Open(src)
if err != nil {
  log.Fatal(err)
}
defer srcFile.Close()

newFile, err := os.Create(dest)
if err != nil {
  log.Fatal(err)
}
defer newFile.Close()

_, err = io.Copy(newFile, srcFile)
if err != nil {
  log.Fatal(err)
}

Rename

Rename is a bit easier to achieve. The os package has a Rename() function. Here’s how to use it:

err := os.Rename(src, dest)

Remove file

To remove file, there’s a Remove() function you can use. Here’s how to use it:

err := os.Remove(path)

Create dir

To create a directory, you can use the MkdirAll() function in the os library. However, you should check whether the directory exist first. The way to do that is to use the IsNotExist() function like so:

_, err := os.Stat(dirName)

 if os.IsNotExist(err) {
  errDir := os.MkdirAll(dirName, 0755)
  if errDir != nil {
   log.Fatal(err)
  }
 } else if err != nil {
  log.Fatal("error creating dir")
 } else {
  log.Fatal("directory exist")
 }

As you can see on the above code:

  1. you first use the Stat() function. The Stat() returns a FileInfo object or an error of type PathError if path doesn’t exist.

  2. os.IsNotExist(err). This returns true if err is a PathError, i.e the path don’t exist, which is good, we want to create it.

  3. Finally, we call os.MkdirAll(dirName, 0755). The 755 instruction is about permissions on the created directory, which gives the permissions, Read/Write/Execute, Read/Execute, Read/Execute. 755 is a common permission set on web servers. You essentially want to avoid anyone but you to modify the file.

Read dir

Reading a directory is quite straight forward. You can use the ReadDir() function on the io/ioutil library. Here’s how you would read a directory:

files, err := ioutil.ReadDir(path)

files is an array of type FileInfo.

TODO, copy, rename, remove, check for existence

Assignment

Create the following files and directories like so:

tmp/
  a.txt
  b.xt
  subdir/

Your program should read the diretory tmp and for each entry list, if it’s a dir or a file, the size and when last modified.

The programs output should look something like:

Reading directory tmp:
Name, Type, Size, Modified
a.txt, file, 1kb, 2022-01-01
b.txt, file, 1kb, 2022-01-01
subdir, directory, 1kb, 2022-01-01

Solution

package main

import (
 "fmt"
 "io/ioutil"
 "log"
)

func GetType(isDir bool) string {
 if isDir {
  return "directory"
 }
 return "file"
}

func main() {
 var path string = "tmp"
 files, err := ioutil.ReadDir(path)
 if err != nil {
  log.Fatal(err)
 }
 fmt.Println("Reading directory ", path)
 fmt.Println("Name, Type, Size, Modified")
 for _, file := range files {
  if err != nil {
   log.Fatal(err)
  }
  fmt.Printf("File Name: %s, ", file.Name())
  fmt.Printf("Type: %s, ", GetType(file.IsDir()))
  fmt.Printf("Size: %d, ", file.Size())             
  fmt.Printf("Last Modified: %s, ", file.ModTime()) 
  fmt.Print("\n")
 }
}