package main import ( "bytes" "fmt" "os" "path/filepath" "strings" ) type Result struct { FilePath string Status string // "ok", "fixed", "error" Message string } func main() { var ( dir = "D:\\Workspace\\f1\\server-feature" //"E:\\f1\\client" //要检查的目录路径 excludes = ".git,Bundles,Library,Logs" //要排除的目录(多个用逗号分隔) dryRun = false //只检查不修复 extName = ".sh" // 要检查的文件扩展名 ) // 解析排除目录 excludeMap := make(map[string]bool) if excludes != "" { for _, ex := range strings.Split(excludes, ",") { excludeMap[strings.TrimSpace(ex)] = true } } fmt.Printf("开始检查目录: %s\n", dir) if dryRun { fmt.Println("【干跑模式 - 不会修改文件】") } if len(excludeMap) > 0 { fmt.Printf("排除目录: %v\n", excludeMap) } fmt.Println() var results []Result // 遍历目录 err := filepath.WalkDir(dir, func(path string, d os.DirEntry, err error) error { if err != nil { results = append(results, Result{ FilePath: path, Status: "error", Message: fmt.Sprintf("访问错误: %v", err), }) return nil } // 检查是否是目录且在排除列表中 if d.IsDir() && excludeMap[d.Name()] { return filepath.SkipDir } // 只处理 .cs 文件 if !d.IsDir() && strings.HasSuffix(strings.ToLower(path), extName) { result := checkAndFixFile(path, dryRun) results = append(results, result) } return nil }) if err != nil { fmt.Printf("遍历目录失败: %v\n", err) os.Exit(1) } // 打印结果 printResults(results) } func checkAndFixFile(filePath string, dryRun bool) Result { // 读取文件 content, err := os.ReadFile(filePath) if err != nil { return Result{ FilePath: filePath, Status: "error", Message: fmt.Sprintf("读取失败: %v", err), } } // 检查是否包含 CRLF if !bytes.Contains(content, []byte("\r\n")) { return Result{ FilePath: filePath, Status: "ok", Message: "已经是LF格式", } } // 替换 CRLF 为 LF fixedContent := bytes.ReplaceAll(content, []byte("\r\n"), []byte("\n")) // 干跑模式不写入 if dryRun { return Result{ FilePath: filePath, Status: "fixed", Message: "发现CRLF(干跑模式未修改)", } } // 写回文件 if err := writeFileContent(filePath, fixedContent); err != nil { return Result{ FilePath: filePath, Status: "error", Message: fmt.Sprintf("写入失败: %v", err), } } return Result{ FilePath: filePath, Status: "fixed", Message: "已修正为LF格式", } } func writeFileContent(filePath string, content []byte) error { // 先写入临时文件,然后重命名,避免数据损坏 tmpPath := filePath + ".tmp" if err := os.WriteFile(tmpPath, content, 0644); err != nil { return err } return os.Rename(tmpPath, filePath) } func printResults(results []Result) { fmt.Println("========== 检查结果 ==========") var okCount, fixedCount, errorCount int for _, r := range results { switch r.Status { case "ok": okCount++ fmt.Printf("✓ %s\n", r.FilePath) case "fixed": fixedCount++ fmt.Printf("⚡ %s - %s\n", r.FilePath, r.Message) case "error": errorCount++ fmt.Printf("✗ %s - %s\n", r.FilePath, r.Message) } } fmt.Printf("\n总计: %d 个文件\n", len(results)) fmt.Printf(" - 正常(LF): %d\n", okCount) fmt.Printf(" - 已修正: %d\n", fixedCount) fmt.Printf(" - 错误: %d\n", errorCount) }