GO语言实现简单的目录复制功能

本文实例讲述了GO语言实现简单的目录复制功能。分享给大家供大家参考。具体实现方法如下:

创建一个独立的 goroutine 遍历文件,主进程负责写入数据。程序会复制空目录,也可以设置只复制以 ".xx" 结尾的文件。
严格来说这不是复制文件,而是写入新文件。因为这个程序是创建新文件,然后写入复制数据的。我们一般的 copy 命令是不会修改文件的 ctime(change time) 状态的。

代码如下:

代码如下:

// 一个简单的目录复制程序:一个独立的 goroutine 遍历目录,主进程负责将数据写入新目录。
// 2014-11-02 Bing.L
package main

import (
 "io"
 "log"
 "os"
 "path/filepath"
 "strings"
)

type FileInfo struct {
 RelPath string
 Size    int64
 IsDir   bool
 Handle  *os.File
}

//复制文件数据
func ioCopy(srcHandle *os.File, dstPth string) (err error) {
 dstHandle, err := os.OpenFile(dstPth, os.O_CREATE|os.O_WRONLY, os.ModePerm)
 if err != nil {
  return err
 }

defer srcHandle.Close()
 defer dstHandle.Close()

_, err = io.Copy(dstHandle, srcHandle)
 return err
}

//遍历目录,将文件信息传入通道
func WalkFiles(srcDir, suffix string, c chan<- *FileInfo) {
 suffix = strings.ToUpper(suffix)

filepath.Walk(srcDir, func(f string, fi os.FileInfo, err error) error { //遍历目录
  if err != nil {
   log.Println("[E]", err)
  }

fileInfo := &FileInfo{}
  if strings.HasSuffix(strings.ToUpper(fi.Name()), suffix) { //匹配文件
   if fh, err := os.OpenFile(f, os.O_RDONLY, os.ModePerm); err != nil {
    log.Println("[E]", err)
   } else {
    fileInfo.Handle = fh
    fileInfo.RelPath, _ = filepath.Rel(srcDir, f) //相对路径
    fileInfo.Size = fi.Size()
    fileInfo.IsDir = fi.IsDir()
   }

c <- fileInfo
  }
 })
 close(c) //遍历完成,关闭通道
}

//写目标文件
func WriteFiles(dstDir string, c <-chan *FileInfo) {
 if err := os.Chdir(dstDir); err != nil { //切换工作路径
  log.Fatalln("[F]", err)
 }

for f := range c {
  if fi, err := os.Stat(f.RelPath); os.IsNotExist(err) { //目标不存在
   if f.IsDir {
    if err := os.MkdirAll(f.RelPath, os.ModeDir); err != nil {
     log.Println("[E]", err)
    }
   } else {
    if err := ioCopy(f.Handle, f.RelPath); err != nil {
     log.Println("[E]", err)
    } else {
     log.Println("[I] CP:", f.RelPath)
    }
   }
  } else if !f.IsDir { //目标存在,而且源不是一个目录

if fi.IsDir() != f.IsDir { //检查文件名被目录名占用冲突
    log.Println("[E]", "filename conflict:", f.RelPath)

} else if fi.Size() != f.Size { //源和目标的大小不一致时才重写
    if err := ioCopy(f.Handle, f.RelPath); err != nil {
     log.Println("[E]", err)
    } else {
     log.Println("[I] CP:", f.RelPath)
    }
   }
  }
 }
}

func main() {
 files_ch := make(chan *FileInfo, 100)

go WalkFiles("E:\\study", ".doc", files_ch) //在一个独立的 goroutine 中遍历文件
 WriteFiles("E:\\study.bak", files_ch)
}

希望本文所述对大家的GO语言程序设计有所帮助。

(0)

相关推荐

  • Go语言编程中判断文件是否存在是创建目录的方法

    判断文件是否存在 os.IsExists()函数和os.IsNotExists(),他们的函数的原形是func IsExist(err error) bool func IsNotExist(err error) bool 都是传入一个err返回bool 这里注意了 err已经定义好了 复制代码 代码如下: /*  var (      ErrInvalid    = errors.New("invalid argument")      ErrPermission = errors.

  • Go语言扫描目录并获取相关信息的方法

    本文实例讲述了Go语言扫描目录并获取相关信息的方法.分享给大家供大家参考.具体分析如下: 前言:最近看到Go里面有一个func很容易就可以扫描整个目录,并且可以得到相应的目录和文件信息,所以我将其进行了封装,拿到file info的所有信息 这样就可以方便的做其它用途了. 直接上代码,代码基于Go version 1 复制代码 代码如下: package main import (     "path/filepath"     "os"     "fla

  • Go语言的GOPATH与工作目录详解

    GOPATH设置 go 命令依赖一个重要的环境变量:$GOPATH1 (注:这个不是Go安装目录.下面以笔者的工作目录为说明,请替换自己机器上的工作目录.) 在类似 Unix 环境大概这样设置: 复制代码 代码如下: export GOPATH=/home/apple/mygo 为了方便,应该把新建以上文件夹,并且把以上一行加入到 .bashrc 或者 .zshrc 或者自己的 sh 的配置文件中. Windows 设置如下,新建一个环境变量名称叫做GOPATH: 复制代码 代码如下: GOPA

  • Go语言正则表达式用法实例小结【查找、匹配、替换等】

    本文实例讲述了Go语言正则表达式用法.分享给大家供大家参考,具体如下: Go语言的正则表达式使用很简单,示例代码: 复制代码 代码如下: package test import (     "fmt"     "regexp" ) func RegixBase() {     //findTest()     //findIndexTest()     //findStringTest()     //findChinesString()     //findNum

  • Go语言文件操作的方法

    本文实例讲述了Go语言文件操作的方法.分享给大家供大家参考.具体如下: 关闭文件: 复制代码 代码如下: func (file *File) Close() os.Error {     if file == nil {         return os.EINVAL     }     e := syscall.Close(file.fd)     file.fd = -1 // so it can't be closed again     if e != 0 {         retu

  • GO语言文件的创建与打开实例分析

    本文实例分析了GO语言文件的创建与打开用法.分享给大家供大家参考.具体分析如下: 文件操作是个很重要的话题,使用也非常频繁,熟悉如何操作文件是必不可少的.Golang 对文件的支持是在 os package 里,具体操作都封装在 type File struct {} 结构体中. 一.func Open(name string) (file *File, err error) 再简单不过了,给一个路径给它,返回文件描述符,如果出现错误就会返回一个 *PathError. 这是一个只读打开模式,实

  • go语言遍历文件夹示例

    用python遍历文件夹很方便,在go的世界里,我也需要这样的功能.找了找文档,里面有这个功能(具体参考这里:http://golang.org/pkg/path/filepath/ )-- 好,不废话了,我也想早点睡,直接上代码. 代码如下: 复制代码 代码如下: /* File      : getFilelist.go Author    : Mike E-Mail    : Mike_Zhang@live.com */ package main import (     "path/fi

  • GO语言实现列出目录和遍历目录的方法

    本文实例讲述了GO语言实现列出目录和遍历目录的方法.分享给大家供大家参考.具体如下: GO语言获取目录列表用 ioutil.ReadDir(),遍历目录用 filepath.Walk(),使用方法课参考本文示例. 具体示例代码如下: 复制代码 代码如下: package main import (  "fmt"  "io/ioutil"  "os"  "path/filepath"  "strings" )

  • Go语言正则表达式示例

    本文实例讲述了Go语言正则表达式.分享给大家供大家参考,具体如下: 复制代码 代码如下: package main import "bytes" import "fmt" import "regexp" func main() { //这个测试一个字符串是否符合一个表达式.     match, _ := regexp.MatchString("p([a-z]+)ch", "peach")     fmt.

  • go语言文件正则表达式搜索功能示例

    本文实例讲述了go语言文件正则表达式搜索功能.分享给大家供大家参考,具体如下: 复制代码 代码如下: package main import (     "fmt"     "os"     "path/filepath"     "regexp" ) func main() {     // 命令行参数     args := os.Args     // 检查参数     if len(args) == 1 {      

随机推荐