Golang : Copy directory - including sub-directories and files
Another day, another tutorial....ok...we will learn how to copy all the content of the directory to another directory with Go. The copy process will perform minimum sanity checks and also ensure all the permission are copied over as well.
copydir.go
package main
import (
"os"
"flag"
"fmt"
"io"
)
func CopyFile(source string, dest string) (err error) {
sourcefile, err := os.Open(source)
if err != nil {
return err
}
defer sourcefile.Close()
destfile, err := os.Create(dest)
if err != nil {
return err
}
defer destfile.Close()
_, err = io.Copy(destfile, sourcefile)
if err == nil {
sourceinfo, err := os.Stat(source)
if err != nil {
err = os.Chmod(dest, sourceinfo.Mode())
}
}
return
}
func CopyDir(source string, dest string) (err error) {
// get properties of source dir
sourceinfo, err := os.Stat(source)
if err != nil {
return err
}
// create dest dir
err = os.MkdirAll(dest, sourceinfo.Mode())
if err != nil {
return err
}
directory, _ := os.Open(source)
objects, err := directory.Readdir(-1)
for _, obj := range objects {
sourcefilepointer := source + "/" + obj.Name()
destinationfilepointer := dest + "/" + obj.Name()
if obj.IsDir() {
// create sub-directories - recursively
err = CopyDir(sourcefilepointer, destinationfilepointer)
if err != nil {
fmt.Println(err)
}
} else {
// perform copy
err = CopyFile(sourcefilepointer, destinationfilepointer)
if err != nil {
fmt.Println(err)
}
}
}
return
}
func main() {
flag.Parse() // get the source and destination directory
source_dir := flag.Arg(0) // get the source directory from 1st argument
dest_dir := flag.Arg(1) // get the destination directory from the 2nd argument
fmt.Println("Source :" + source_dir)
// check if the source dir exist
src, err := os.Stat(source_dir)
if err != nil {
panic(err)
}
if !src.IsDir() {
fmt.Println("Source is not a directory")
os.Exit(1)
}
// create the destination directory
fmt.Println("Destination :"+ dest_dir)
_, err = os.Open(dest_dir)
if !os.IsNotExist(err) {
fmt.Println("Destination directory already exists. Abort!")
os.Exit(1)
}
err = CopyDir(source_dir, dest_dir)
if err != nil {
fmt.Println(err)
} else {
fmt.Println("Directory copied")
}
}
Build the program by executing >go build copydir.go
and the execute >/copydir /Users/admin/source_test /Users/admin/test
Source :/Users/admin/source_test
Destination :/Users/admin/test
Directory copied
NOTE
I've tried to implement this with filepath.walk()
but encountered problem in calling the function recursively. Therefore, at this time of writing, I will use readdir(-1)
Good to know :
https://www.socketloop.com/tutorials/golang-read-directory-content-with-filepath-walk
See also : Golang : Read directory content with os.Open
By Adam Ng
IF you gain some knowledge or the information here solved your programming problem. Please consider donating to the less fortunate or some charities that you like. Apart from donation, planting trees, volunteering or reducing your carbon footprint will be great too.
Advertisement
Tutorials
+5.3k Golang : Pad file extension automagically
+17.1k Google Chrome : Your connection to website is encrypted with obsolete cryptography
+13.7k Golang : Convert spaces to tabs and back to spaces example
+21k Golang : Get password from console input without echo or masked
+4.7k Golang : A program that contain another program and executes it during run-time
+7.3k Golang : How to convert strange string to JSON with json.MarshalIndent
+23.8k Golang : Call function from another package
+7.2k Golang : How to iterate a slice without using for loop?
+5.7k Golang : Error handling methods
+10k Golang : How to tokenize source code with text/scanner package?
+32.6k Golang : Regular Expression for alphanumeric and underscore
+8.9k Golang : How to use Gorilla webtoolkit context package properly