In this tutorial series #6, we will learn how to copy the entire folder or directory using Golang programming language with step by step guide.
Installed Packages:
https://github.com/fatih/color
https://github.com/itrepablik/itrlog
https://github.com/itrepablik/kopy
https://github.com/spf13/cobra
#MaharlikansCode
#CopyFolderInGo
#Golang
#LifeAsSoftwareDeveloper
#Maharlikans
#FilipinoSoftwareDeveloper
If you go with extra mile for buying me a cup of coffee, I appreciate it guys: https://ko-fi.com/maharlikanscode
Source Codes:
cmd/copydir.go:
package cmd
import (
"fmt"
"path/filepath"
"time"
"github.com/fatih/color"
"github.com/itrepablik/itrlog"
"github.com/itrepablik/kopy"
"github.com/spf13/cobra"
)
// copydirCmd represents the copydir command
var copydirCmd = &cobra.Command{
Use: "copydir",
Short: "Copy the entire folder or a directory without a compression",
Long: `copydir command is to copy the entire directory or folder including its sub-folders and sub-directories contents.
Warning: it will replace any existing files and its contents to the destination directory or a folder.
Example of a valid directory path in Windows:
"C:\source_folder" "D:\backup_destination"
Or using the network directories, example:
"\\hostname_or_ip\source_folder" "\\hostname_or_ip\backup_destination"`,
Args: cobra.MinimumNArgs(2),
Run: func(cmd *cobra.Command, args []string) {
// To make directory path separator a universal, in Linux "/" and in Windows "\" to auto change
// depends on the user's OS using the filepath.FromSlash organic Go's library.
src := filepath.FromSlash(args[0])
dst := filepath.FromSlash(args[1])
msg := `Starts copying the entire directory or a folder: `
color.Blue(msg + " " + src)
itrlog.Infow(msg, "src", src, "log_time", time.Now().Format(logDTFormat))
// Starts copying the entire directory or a folder.
filesCopied, foldersCopied, err := kopy.CopyDir(src, dst, copydirLog, copydirIgnore)
if err != nil {
color.Red(err.Error())
itrlog.Errorw("error", "err", err, "log_time", time.Now().Format(logDTFormat))
return
}
// Give some info back to the user's console and the logs as well.
msg = `Done copied the entire directory or a folder: `
color.Green(msg + " " + src + " Number of Folders Copied: " + fmt.Sprintf("%v", filesCopied) + " Number of Files Copied: " + fmt.Sprintf("%v", foldersCopied))
itrlog.Infow(msg, "src", src, "dst", dst, "folder_copied", filesCopied, "files_copied", foldersCopied, "log_time", time.Now().Format(logDTFormat))
},
}
func init() {
rootCmd.AddCommand(copydirCmd)
}
kopy.CopyDir:
// CopyDir copies a whole directory recursively and its sub-directories.
func CopyDir(src, dst string, isLogCopiedFile bool, ignoreFT []string) (int, int, error) {
var err error
var fds []os.FileInfo
var srcinfo os.FileInfo
var numCopiedFiles, numCopiedFolders int = 0, 0
if srcinfo, err = os.Stat(src); err != nil {
color.Red(err.Error())
itrlog.Errorw("error", "err", err, "log_time", time.Now().Format(logDateTimeFormat))
return int(numCopiedFolders), int(numCopiedFiles), err
}
if err = os.MkdirAll(dst, srcinfo.Mode()); err != nil {
color.Red(err.Error())
itrlog.Errorw("error", "err", err, "log_time", time.Now().Format(logDateTimeFormat))
return int(numCopiedFolders), int(numCopiedFiles), err
}
if fds, err = ioutil.ReadDir(src); err != nil {
color.Red(err.Error())
itrlog.Errorw("error", "err", err, "log_time", time.Now().Format(logDateTimeFormat))
return int(numCopiedFolders), int(numCopiedFiles), err
}
for _, fd := range fds {
srcfp := path.Join(src, fd.Name())
dstfp := path.Join(dst, fd.Name())
_continue := false
for _, i := range ignoreFT {
if strings.Index(srcfp, strings.TrimSpace(i)) != -1 {
// Only log when it's true
if isLogCopiedFile {
itrlog.Infow("ignored", "file", filepath.FromSlash(srcfp), "log_time", time.Now().Format(logDateTimeFormat))
color.Yellow("ignored: " + filepath.FromSlash(srcfp))
}
_continue = true // Ignore files and folders here
}
}
if _continue == false {
if fd.IsDir() {
if _, _, err = CopyDir(srcfp, dstfp, isLogCopiedFile, ignoreFT); err != nil {
color.Red(err.Error())
itrlog.Errorw("error", "err", err, "log_time", time.Now().Format(logDateTimeFormat))
} else {
numCopiedFolders++
// Only log when it's true
if isLogCopiedFile {
itrlog.Infow("copied_folder", "name", fd.Name(), "log_time", time.Now().Format(logDateTimeFormat))
color.Cyan("copied folder: " + fd.Name())
}
}
} else {
if err = CopyFile(srcfp, dstfp, dst); err != nil {
color.Red(err.Error())
itrlog.Errorw("error", "err", err, "log_time", time.Now().Format(logDateTimeFormat))
} else {
numCopiedFiles++
// Only log when it's true
if isLogCopiedFile {
Source codes omitted due to not enough space.