批量替换和转移目录的东东
2015-10-24 01:34
666 查看
拷,1点半了,写太晚了。 总之是个好东东。直接上代码了,不解释。
/*
批量替换和转移目录的东东
遍历指定目录(包含子目录),对于指定扩展名的文件, 查找并替换文件内容中的指定字符串,并
将其输出到新的目录(包含子目录)下。原文件内容不变。
至于其它非指定的文件,也一并复制一份到新目录下。
使用Josn作为配置文件.
Author:XiongChuanLiang
Date:2015-10-23
Linux 配置示例:
{
"sourcedir":"/home/xcl/test/t1/",
"destdir":"/home/xcl/test/t2/",
"fileext":[".go",".conf"],
"replacewhere":[{
"findwhat":"V9",
"replacewith":"V10"
},
{
"findwhat":"172.18.1.101",
"replacewith":"192.168.1.101"
}]
}
注意:
sourcedir与destdir 配置时要对整齐,且最后要加"/".
*/
package main
import (
"bufio"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
"runtime"
"strings"
"sync"
"time"
)
const (
flagFile = "flag.json"
)
type RWhere struct {
FindWhat string `json:"findwhat"`
ReplaceWith string `json:"replacewith"`
}
type ReplaceConf struct {
SourceDir string `json:"sourcedir"`
DestDir string `json:"destdir"`
FileExtension []string `json:"fileext"`
ReplaceWhere []RWhere `json:"replacewhere"`
CaseSensitive bool `json:"casesensitive,omitempty"`
}
var repConf ReplaceConf
var repReplacer *strings.Replacer
var extFileNum, otherFileNum int
var maxGoroutines int
func init() {
maxGoroutines = 10
}
func main() {
now := time.Now()
runtime.GOMAXPROCS(runtime.NumCPU())
parseJsonFile()
findSourceFiles(repConf.SourceDir)
end_time := time.Now()
var dur_time time.Duration = end_time.Sub(now)
fmt.Printf("elapsed %f seconds\n", dur_time.Seconds())
fmt.Println("处理统计")
fmt.Println(" 处理指定类型文件:", extFileNum)
fmt.Println(" 处理其它文件:", otherFileNum)
}
func findSourceFiles(dirname string) {
waiter := &sync.WaitGroup{}
fmt.Println("dirname:", dirname)
filepath.Walk(dirname, sourceWalkFunc(waiter))
waiter.Wait()
}
func sourceWalkFunc(waiter *sync.WaitGroup) func(string, os.FileInfo, error) error {
return func(path string, info os.FileInfo, err error) error {
if err == nil && info.Size() > 0 && !info.IsDir() {
if runtime.NumGoroutine() > maxGoroutines {
parseFile(path, nil)
} else {
waiter.Add(1)
go parseFile(path, func() { waiter.Done() })
}
} else {
fmt.Println("[sourceWalkFunc] err:", err)
}
return nil
}
}
func parseFile(currfile string, done func()) {
if done != nil {
defer done()
}
//这地方要注意,配置要对。
destFile := strings.Replace(currfile, repConf.SourceDir, repConf.DestDir, -1)
if destFile == currfile {
panic("[parseFile] ERROR 没有替换对. SourceDir与DestDir配置出问题了。请检查Json配置.")
}
destDir := filepath.Dir(destFile)
if _, er := os.Stat(destDir); os.IsNotExist(er) {
if err := os.MkdirAll(destDir, 0700); err != nil {
fmt.Println("[parseFile] MkdirAll ", destDir)
panic(err)
}
}
fmt.Println("[parseFile] 源文件:", currfile)
fmt.Println("[parseFile] 目标文件:", destFile)
/////////////////////////////////////////////////
oldFile, err := os.Open(currfile)
if err != nil {
fmt.Println("[parseFile] Failed to open the input file ", oldFile)
return
}
defer oldFile.Close()
newFile, err := os.Create(destFile)
if err != nil {
panic(err)
}
defer newFile.Close()
f1 := func(ext string) bool {
for _, e := range repConf.FileExtension {
if ext == e {
return true
}
}
return false
}
if f1(filepath.Ext(currfile)) {
copyRepFile(newFile, oldFile)
extFileNum++
} else {
if _, err := io.Copy(newFile, oldFile); err != nil {
panic(err)
}
otherFileNum++
}
}
func copyRepFile(newFile, oldFile *os.File) {
br := bufio.NewReader(oldFile)
bw := bufio.NewWriter(newFile)
for {
row, err1 := br.ReadString(byte('\n'))
if err1 != nil {
break
}
str := string(row)
if str == "" {
continue
}
ret := repReplacer.Replace(str)
//fmt.Println("[copyRepFile] str:", str)
//fmt.Println("[copyRepFile] ret:", ret)
if _, err := bw.WriteString(ret); err != nil {
panic(err)
}
}
bw.Flush()
}
func parseJsonFile() {
f, err := os.Open(flagFile)
if err != nil {
panic("[parseJsonFile] open failed!")
}
defer f.Close()
j, err := ioutil.ReadAll(f)
if err != nil {
panic("[parseJsonFile] ReadAll failed!")
}
err = json.Unmarshal(j, &repConf)
if err != nil {
fmt.Println("[parseJsonFile] json err:", err)
panic("[parseJsonFile] Unmarshal failed!")
}
fmt.Println(" ------------------------------------------------------")
fmt.Println(" 源目录:", repConf.SourceDir)
fmt.Println(" 目标目录:", repConf.DestDir)
fmt.Println(" 仅包含的指定扩展名的文件:", repConf.FileExtension)
for _, e := range repConf.FileExtension {
fmt.Println(" 文件扩展名:", e)
}
arr := make([]string, 0, 1)
for _, v := range repConf.ReplaceWhere {
fmt.Println(" 原文本:", v.FindWhat, " 替换为:", v.ReplaceWith)
arr = append(arr, v.FindWhat)
arr = append(arr, v.ReplaceWith)
}
repReplacer = strings.NewReplacer(arr...)
fmt.Println(" ------------------------------------------------------")
if repConf.SourceDir == "" || repConf.DestDir == "" {
panic("[parseJsonFile] 目录设置不对!")
}
}
贴一个Windows下的例子:
就不演示包含子目录的了。 其中参数就是把Json内容存到“flag.json”文件里,运行时会自动去读取配置。
BLOG: http://blog.csdn.net/xcl168
/*
批量替换和转移目录的东东
遍历指定目录(包含子目录),对于指定扩展名的文件, 查找并替换文件内容中的指定字符串,并
将其输出到新的目录(包含子目录)下。原文件内容不变。
至于其它非指定的文件,也一并复制一份到新目录下。
使用Josn作为配置文件.
Author:XiongChuanLiang
Date:2015-10-23
Linux 配置示例:
{
"sourcedir":"/home/xcl/test/t1/",
"destdir":"/home/xcl/test/t2/",
"fileext":[".go",".conf"],
"replacewhere":[{
"findwhat":"V9",
"replacewith":"V10"
},
{
"findwhat":"172.18.1.101",
"replacewith":"192.168.1.101"
}]
}
注意:
sourcedir与destdir 配置时要对整齐,且最后要加"/".
*/
package main
import (
"bufio"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
"runtime"
"strings"
"sync"
"time"
)
const (
flagFile = "flag.json"
)
type RWhere struct {
FindWhat string `json:"findwhat"`
ReplaceWith string `json:"replacewith"`
}
type ReplaceConf struct {
SourceDir string `json:"sourcedir"`
DestDir string `json:"destdir"`
FileExtension []string `json:"fileext"`
ReplaceWhere []RWhere `json:"replacewhere"`
CaseSensitive bool `json:"casesensitive,omitempty"`
}
var repConf ReplaceConf
var repReplacer *strings.Replacer
var extFileNum, otherFileNum int
var maxGoroutines int
func init() {
maxGoroutines = 10
}
func main() {
now := time.Now()
runtime.GOMAXPROCS(runtime.NumCPU())
parseJsonFile()
findSourceFiles(repConf.SourceDir)
end_time := time.Now()
var dur_time time.Duration = end_time.Sub(now)
fmt.Printf("elapsed %f seconds\n", dur_time.Seconds())
fmt.Println("处理统计")
fmt.Println(" 处理指定类型文件:", extFileNum)
fmt.Println(" 处理其它文件:", otherFileNum)
}
func findSourceFiles(dirname string) {
waiter := &sync.WaitGroup{}
fmt.Println("dirname:", dirname)
filepath.Walk(dirname, sourceWalkFunc(waiter))
waiter.Wait()
}
func sourceWalkFunc(waiter *sync.WaitGroup) func(string, os.FileInfo, error) error {
return func(path string, info os.FileInfo, err error) error {
if err == nil && info.Size() > 0 && !info.IsDir() {
if runtime.NumGoroutine() > maxGoroutines {
parseFile(path, nil)
} else {
waiter.Add(1)
go parseFile(path, func() { waiter.Done() })
}
} else {
fmt.Println("[sourceWalkFunc] err:", err)
}
return nil
}
}
func parseFile(currfile string, done func()) {
if done != nil {
defer done()
}
//这地方要注意,配置要对。
destFile := strings.Replace(currfile, repConf.SourceDir, repConf.DestDir, -1)
if destFile == currfile {
panic("[parseFile] ERROR 没有替换对. SourceDir与DestDir配置出问题了。请检查Json配置.")
}
destDir := filepath.Dir(destFile)
if _, er := os.Stat(destDir); os.IsNotExist(er) {
if err := os.MkdirAll(destDir, 0700); err != nil {
fmt.Println("[parseFile] MkdirAll ", destDir)
panic(err)
}
}
fmt.Println("[parseFile] 源文件:", currfile)
fmt.Println("[parseFile] 目标文件:", destFile)
/////////////////////////////////////////////////
oldFile, err := os.Open(currfile)
if err != nil {
fmt.Println("[parseFile] Failed to open the input file ", oldFile)
return
}
defer oldFile.Close()
newFile, err := os.Create(destFile)
if err != nil {
panic(err)
}
defer newFile.Close()
f1 := func(ext string) bool {
for _, e := range repConf.FileExtension {
if ext == e {
return true
}
}
return false
}
if f1(filepath.Ext(currfile)) {
copyRepFile(newFile, oldFile)
extFileNum++
} else {
if _, err := io.Copy(newFile, oldFile); err != nil {
panic(err)
}
otherFileNum++
}
}
func copyRepFile(newFile, oldFile *os.File) {
br := bufio.NewReader(oldFile)
bw := bufio.NewWriter(newFile)
for {
row, err1 := br.ReadString(byte('\n'))
if err1 != nil {
break
}
str := string(row)
if str == "" {
continue
}
ret := repReplacer.Replace(str)
//fmt.Println("[copyRepFile] str:", str)
//fmt.Println("[copyRepFile] ret:", ret)
if _, err := bw.WriteString(ret); err != nil {
panic(err)
}
}
bw.Flush()
}
func parseJsonFile() {
f, err := os.Open(flagFile)
if err != nil {
panic("[parseJsonFile] open failed!")
}
defer f.Close()
j, err := ioutil.ReadAll(f)
if err != nil {
panic("[parseJsonFile] ReadAll failed!")
}
err = json.Unmarshal(j, &repConf)
if err != nil {
fmt.Println("[parseJsonFile] json err:", err)
panic("[parseJsonFile] Unmarshal failed!")
}
fmt.Println(" ------------------------------------------------------")
fmt.Println(" 源目录:", repConf.SourceDir)
fmt.Println(" 目标目录:", repConf.DestDir)
fmt.Println(" 仅包含的指定扩展名的文件:", repConf.FileExtension)
for _, e := range repConf.FileExtension {
fmt.Println(" 文件扩展名:", e)
}
arr := make([]string, 0, 1)
for _, v := range repConf.ReplaceWhere {
fmt.Println(" 原文本:", v.FindWhat, " 替换为:", v.ReplaceWith)
arr = append(arr, v.FindWhat)
arr = append(arr, v.ReplaceWith)
}
repReplacer = strings.NewReplacer(arr...)
fmt.Println(" ------------------------------------------------------")
if repConf.SourceDir == "" || repConf.DestDir == "" {
panic("[parseJsonFile] 目录设置不对!")
}
}
贴一个Windows下的例子:
Windows配置例子: { "sourcedir":"E:\\xclgo\\src\\test\\aaa\\", "destdir":"E:\\xclgo\\src\\test\\bbb\\", "fileext":[".go",".conf"], "replacewhere":[{ "findwhat":"parseFile", "replacewith":"----parseFile----" }, { "findwhat":"172.18.1.101", "replacewith":"192.168.1.101" }] } 运行结果: E:\xclgo\src\test>go run batchreplace.go ------------------------------------------------------ 源目录: E:\xclgo\src\test\aaa\ 目标目录: E:\xclgo\src\test\bbb\ 仅包含的指定扩展名的文件: [.go .conf] 文件扩展名: .go 文件扩展名: .conf 原文本: parseFile 替换为: ----parseFile---- 原文本: 172.18.1.101 替换为: 192.168.1.101 ------------------------------------------------------ dirname: E:\xclgo\src\test\aaa\ [sourceWalkFunc] err: <nil> [parseFile] 源文件: E:\xclgo\src\test\aaa\testfile.go [parseFile] 目标文件: E:\xclgo\src\test\bbb\testfile.go elapsed 0.004000 seconds 处理统计 处理指定类型文件: 1 处理其它文件: 0
就不演示包含子目录的了。 其中参数就是把Json内容存到“flag.json”文件里,运行时会自动去读取配置。
BLOG: http://blog.csdn.net/xcl168
相关文章推荐
- Go 语言 Channel 实现原理精要
- Go语言将支持Android
- SQLSERVER 中GO的作用详解
- Shell脚本实现批量替换文件内容
- MSSQL批量替换语句 在SQL SERVER中批量替换字符串的方法
- Access中批量替换数据库内容的两种方法
- Golang实现的聊天程序服务端和客户端代码分享
- 批量替换 MySQL 指定字段中的字符串
- Discuz批量替换帖子内容的方法(使用SQL更新数据库)
- php 批量替换html标签的实例代码
- GO语言类型转换和类型断言实例分析
- Golang学习笔记(三):控制流
- Golang学习笔记(二):类型、变量、常量
- Go语言实现的最简单数独解法
- Golang中的sync.WaitGroup用法实例
- Go实现比较时间大小
- Go语言struct类型介绍
- golang使用正则表达式解析网页
- Golang极简入门教程(三):并发支持
- 在Go程序中实现服务器重启的方法