Copy files and preserve permission in Golang [SOLVED]


GOLANG Solutions, GO

In this article, we shall be discussing how to copy files and preserve permission in Golang with help of practical examples.

 

Different methods to copy files and preserve permission

Copy is a way of making similar files or directory data from one directory into another. In Golang, we can make use of os, io, and ioutil packages to create functions that can copy files or directories from one source to the destination defined. Below are the methods we shall be using:-

  • Using io package:- provides io.Copy() function
  • Using io packages:- provides os.Rename() function
  • Using ioutil package:- ioutil.Read() and ioutil.Write() functions

 

Method 1:- Using io.Copy() function

In Golang, Os the package provides Stat and Chmod function which can be used to first check the permission of source file and then change the permission of destination file accordingly.

package main

import (
	"fmt"
	"io"
	"os"
)

var srcFile = "source_file.txt"
var dstFile = "/tmp/destination_file.txt"

func main() {
	// Provide the path of source file
	src, err := os.Open(srcFile)
	if err != nil {
		fmt.Print("Failed to open ", srcFile)
		panic(err)
	}
	defer src.Close()

	// check srcFile stats
	fileStat, err := os.Stat(srcFile)
	if err != nil {
		fmt.Print("Failed to check stats for ", srcFile)
		panic(err)
	}

	// print srcFile stats
	perm := fileStat.Mode().Perm()
	fmt.Printf("File permission before copying %v \n", perm)

	// Create the destination file with default permission
	dst, err := os.Create(dstFile)
	if err != nil {
		fmt.Print("Failed to create ", dstFile)
		panic(err)
	}
	defer dst.Close()

	// preserve permissions from srcFile to dstFile
	srcStat, _ := src.Stat()
	fmt.Println("Changing permission of ", dstFile)
	os.Chmod(dstFile, srcStat.Mode())

	// check dstFile stats
	newFileStats, err := os.Stat(dstFile)
	if err != nil {
		fmt.Print("Failed to check stats for ", dstFile)
		panic(err)
	}

	// print dstFile stats
	perm2 := newFileStats.Mode().Perm()
	fmt.Printf("File permission After copying %v \n", perm2)

	// Copy the content of srcFile to dstFile
	if _, err := io.Copy(dstFile, srcFile); err != nil {
		fmt.Print("Copy operation failed")
		panic(err)
	}

}

Output:

# go run main.go 
File permission before copying -r-------- 
Changing permission of  /tmp/destination_file.txt
File permission After copying -r--------

This code will first create an empty destination file and then uses os.Stat function to get the metadata of the source file, including its permissions. It then later applies the same permission from source to destination file using os.Chmod function.

 

Method 2:-Using os.Rename() function

io package is a Goang standard library that enables us to copy files from source to destination. its similar to the above method. However, it accepts two parameters namely, filename and destination name as shown below. It returns two parameters, integer, and error.

Example:-

package main

import (
	"fmt"
	"os"
)

var srcFile = "source_file.txt"
var dstFile = "/tmp/destination_file.txt"

func main() {

	// check srcFile stats
	fileStat, err := os.Stat(srcFile)
	if err != nil {
		fmt.Print("Failed to check stats for ", srcFile)
		panic(err)
	}

	// print srcFile stats
	perm := fileStat.Mode().Perm()
	fmt.Printf("File permission before copying %v \n", perm)

	// Copy srcFile to dstFile
	err = os.Rename(srcFile, dstFile)
	if err != nil {
		fmt.Println("Failed to rename ", srcFile)
		panic(err)
	}

	// check dstFile stats
	newFileStats, err := os.Stat(dstFile)
	if err != nil {
		fmt.Print("Failed to check stats for ", dstFile)
		panic(err)
	}

	// preserve permission
	err = os.Chmod(dstFile, fileStat.Mode())
	if err != nil {
		fmt.Println("Failed to apply permission on ", dstFile)
		panic(err)
	}

	// print dstFile stats
	perm2 := newFileStats.Mode().Perm()
	fmt.Printf("File permission After copying %v \n", perm2)

}

Output:

# touch source_file.txt
# chmod 450 source_file.txt 

# go run main.go 
File permission before copying -r--r-x--- 
File permission After copying -r--r-x---

This code uses os.Stat function to get the metadata details of the source file, including the permission of the file. It will then use os.Rename() function to rename the source file to the destination file path. Then it again uses os.Stat to get the destination file metadata, and it uses the os.Chmod function to set the permissions of the destination file same as of the source file.

 

Method 3:-Using ioutil.ReadFile()and ioutil.WriteFile() functions in Golang

In this method, we will be focusing on ioutil package, which provides us with ioutil.ReadFile() and ioutil.WriteFile() functions. The Read() function reads the file content into bytes and the Write() function just performs the act of writing the bytes into the desired final destination file. The below example explains how to implement the two functions.

Example of Using ioutil.ReadFile()and ioutil.WriteFile() functions in Golang

package main

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

var srcFile = "source_file.txt"
var dstFile = "/tmp/destination_file.txt"

func main() {

	// check srcFile stats
	fileStat, err := os.Stat(srcFile)
	if err != nil {
		fmt.Print("Failed to check stats for ", srcFile)
		panic(err)
	}

	// print srcFile stats
	perm := fileStat.Mode().Perm()
	fmt.Printf("File permission before copying %v \n", perm)

	// read srcFile
	srcContent, err := ioutil.ReadFile(srcFile)
	if err != nil {
		fmt.Print("Failed to read file ", srcFile)
		panic(err)
	}

	// create dstFile and copy the content
	err = ioutil.WriteFile(dstFile, srcContent, fileStat.Mode())
	if err != nil {
		fmt.Print("Failed to copy content into ", dstFile)
		panic(err)
	}

	// check dstFile stats
	newFileStats, err := os.Stat(dstFile)
	if err != nil {
		fmt.Print("Failed to check stats for ", dstFile)
		panic(err)
	}

	// print dstFile stats
	perm2 := newFileStats.Mode().Perm()
	fmt.Printf("File permission After copying %v \n", perm2)

}

Output:

# touch source_file.txt
# chmod 450 source_file.txt 
# echo hello > source_file.txt 

# go run main.go 
File permission before copying -r--r-x--- 
File permission After copying -r--r-x--- 

# cat /tmp/destination_file.txt 
hello

This code uses os.Stat() function to get the metadata details of the source file, including the permission of the file. Here instead of using os.Chmod() we are using ioutil.ReadFile() to read the content of the source file and the ioutil.WriteFile() to create the destination file and copy the contents of the source file, it also uses the third parameter to set the permissions of the destination file that match the permissions of the source file.

 

Summary

In this article, we have covered various ways to copy files and reserve their original permissions. In Golang we can achieve this by using Golang standard library provided such as os, ioutil,  and io packages. this is helpful in transferring files from one server to another in the software development lifecycle.

 

References

ioutil/io
os

 

Views: 85
Deepak Prasad

Deepak Prasad

He is the founder of GoLinuxCloud and brings over a decade of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive experience, he excels in various domains, from development to DevOps, Networking, and Security, ensuring robust and efficient solutions for diverse projects. You can connect with him on his LinkedIn profile.

Can't find what you're searching for? Let us assist you.

Enter your query below, and we'll provide instant results tailored to your needs.

If my articles on GoLinuxCloud has helped you, kindly consider buying me a coffee as a token of appreciation.

Buy GoLinuxCloud a Coffee

For any other feedbacks or questions you can send mail to admin@golinuxcloud.com

Thank You for your support!!

2 thoughts on “Copy files and preserve permission in Golang [SOLVED]”

  1. This does not seem to copy the permissions.
    It appears to because it’s the default permissions.
    os.Create uses the default 0666
    To copy the permissions you need to use os.OpenFile

    Reply

Leave a Comment