main.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. package main
  2. import (
  3. "bytes"
  4. "fmt"
  5. "os"
  6. "path/filepath"
  7. "strings"
  8. )
  9. type Result struct {
  10. FilePath string
  11. Status string // "ok", "fixed", "error"
  12. Message string
  13. }
  14. func main() {
  15. var (
  16. dir = "D:\\Workspace\\f1\\server-feature" //"E:\\f1\\client" //要检查的目录路径
  17. excludes = ".git,Bundles,Library,Logs" //要排除的目录(多个用逗号分隔)
  18. dryRun = false //只检查不修复
  19. extName = ".sh" // 要检查的文件扩展名
  20. )
  21. // 解析排除目录
  22. excludeMap := make(map[string]bool)
  23. if excludes != "" {
  24. for _, ex := range strings.Split(excludes, ",") {
  25. excludeMap[strings.TrimSpace(ex)] = true
  26. }
  27. }
  28. fmt.Printf("开始检查目录: %s\n", dir)
  29. if dryRun {
  30. fmt.Println("【干跑模式 - 不会修改文件】")
  31. }
  32. if len(excludeMap) > 0 {
  33. fmt.Printf("排除目录: %v\n", excludeMap)
  34. }
  35. fmt.Println()
  36. var results []Result
  37. // 遍历目录
  38. err := filepath.WalkDir(dir, func(path string, d os.DirEntry, err error) error {
  39. if err != nil {
  40. results = append(results, Result{
  41. FilePath: path,
  42. Status: "error",
  43. Message: fmt.Sprintf("访问错误: %v", err),
  44. })
  45. return nil
  46. }
  47. // 检查是否是目录且在排除列表中
  48. if d.IsDir() && excludeMap[d.Name()] {
  49. return filepath.SkipDir
  50. }
  51. // 只处理 .cs 文件
  52. if !d.IsDir() && strings.HasSuffix(strings.ToLower(path), extName) {
  53. result := checkAndFixFile(path, dryRun)
  54. results = append(results, result)
  55. }
  56. return nil
  57. })
  58. if err != nil {
  59. fmt.Printf("遍历目录失败: %v\n", err)
  60. os.Exit(1)
  61. }
  62. // 打印结果
  63. printResults(results)
  64. }
  65. func checkAndFixFile(filePath string, dryRun bool) Result {
  66. // 读取文件
  67. content, err := os.ReadFile(filePath)
  68. if err != nil {
  69. return Result{
  70. FilePath: filePath,
  71. Status: "error",
  72. Message: fmt.Sprintf("读取失败: %v", err),
  73. }
  74. }
  75. // 检查是否包含 CRLF
  76. if !bytes.Contains(content, []byte("\r\n")) {
  77. return Result{
  78. FilePath: filePath,
  79. Status: "ok",
  80. Message: "已经是LF格式",
  81. }
  82. }
  83. // 替换 CRLF 为 LF
  84. fixedContent := bytes.ReplaceAll(content, []byte("\r\n"), []byte("\n"))
  85. // 干跑模式不写入
  86. if dryRun {
  87. return Result{
  88. FilePath: filePath,
  89. Status: "fixed",
  90. Message: "发现CRLF(干跑模式未修改)",
  91. }
  92. }
  93. // 写回文件
  94. if err := writeFileContent(filePath, fixedContent); err != nil {
  95. return Result{
  96. FilePath: filePath,
  97. Status: "error",
  98. Message: fmt.Sprintf("写入失败: %v", err),
  99. }
  100. }
  101. return Result{
  102. FilePath: filePath,
  103. Status: "fixed",
  104. Message: "已修正为LF格式",
  105. }
  106. }
  107. func writeFileContent(filePath string, content []byte) error {
  108. // 先写入临时文件,然后重命名,避免数据损坏
  109. tmpPath := filePath + ".tmp"
  110. if err := os.WriteFile(tmpPath, content, 0644); err != nil {
  111. return err
  112. }
  113. return os.Rename(tmpPath, filePath)
  114. }
  115. func printResults(results []Result) {
  116. fmt.Println("========== 检查结果 ==========")
  117. var okCount, fixedCount, errorCount int
  118. for _, r := range results {
  119. switch r.Status {
  120. case "ok":
  121. okCount++
  122. fmt.Printf("✓ %s\n", r.FilePath)
  123. case "fixed":
  124. fixedCount++
  125. fmt.Printf("⚡ %s - %s\n", r.FilePath, r.Message)
  126. case "error":
  127. errorCount++
  128. fmt.Printf("✗ %s - %s\n", r.FilePath, r.Message)
  129. }
  130. }
  131. fmt.Printf("\n总计: %d 个文件\n", len(results))
  132. fmt.Printf(" - 正常(LF): %d\n", okCount)
  133. fmt.Printf(" - 已修正: %d\n", fixedCount)
  134. fmt.Printf(" - 错误: %d\n", errorCount)
  135. }