// 2014-11-02
package main
import (
"io"
"log"
"os"
"path/filepath"
"strings"
)
type FileInfo struct {
RelPath string
Size int64
IsDir bool
Handle *
}
//Copy file data
func ioCopy(srcHandle *, dstPth string) (err error) {
dstHandle, err := (dstPth, os.O_CREATE|os.O_WRONLY, )
if err != nil {
return err
}
defer ()
defer ()
_, err = (dstHandle, srcHandle)
return err
}
//Travel over the directory and pass file information into the channel
func WalkFiles(srcDir, suffix string, c chan<- *FileInfo) {
suffix = (suffix)
(srcDir, func(f string, fi, err error) error { //Travel the directory
if err != nil {
("[E]", err)
}
fileInfo := &FileInfo{}
if ((()), suffix) { //Match the file
if fh, err := (f, os.O_RDONLY, ); err != nil {
("[E]", err)
} else {
= fh
_ = (srcDir, f) //Relative path
= ()
= ()
}
c <- fileInfo
}
})
close(c) //The traversal is completed, the channel is closed
}
//Write the target file
func WriteFiles(dstDir string, c <-chan *FileInfo) {
if err := (dstDir); err != nil { //Switch working path
("[F]", err)
}
for f := range c {
if fi, err := (); (err) { //The target does not exist
if {
if err := (, ); err != nil {
("[E]", err)
}
} else {
if err := ioCopy(, ); err != nil {
("[E]", err)
} else {
("[I] CP:", )
}
}
} else if ! { //The target exists, and the source is not a directory
if () != { //Check the file name to conflict with directory name occupation
("[E]", "filename conflict:", )
} else if () != { //Rewrite only if the sizes of the source and the target are inconsistent
if err := ioCopy(, ); err != nil {
("[E]", err)
} else {
("[I] CP:", )
}
}
}
}
}
func main() {
files_ch := make(chan *FileInfo, 100)
go WalkFiles("E:\\study", ".doc", files_ch) //Transfer files in a separate goroutine
WriteFiles("E:\\", files_ch)
}