| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160 |
- package main
- import (
- "fmt"
- "os"
- "path/filepath"
- "strings"
- )
- const (
- utf8BOMPrefix = "\xEF\xBB\xBF" // UTF-8 BOM 标记
- )
- func main() {
- dirPath := "E:\\f1\\client"
- // 验证目录是否存在
- if info, err := os.Stat(dirPath); err != nil || !info.IsDir() {
- fmt.Printf("Error: %s is not a valid directory\n", dirPath)
- os.Exit(1)
- }
- // 构建屏蔽目录集合,加快查找速度
- excludeSet := make(map[string]bool)
- excludeSet["Library"] = true
- excludeSet["Packages"] = true
- excludeSet["Temp"] = true
- excludeSet[".git"] = true
- // 遍历目录
- err := filepath.WalkDir(dirPath, func(path string, d os.DirEntry, err error) error {
- if err != nil {
- fmt.Fprintf(os.Stderr, "Warning: cannot access %s: %v\n", path, err)
- return filepath.SkipDir // 跳过出错目录,而不是完全终止
- }
- // 检查是否是需要屏蔽的目录
- if d.IsDir() && excludeSet[d.Name()] {
- return filepath.SkipDir // 跳过当前目录及其子目录
- }
- // 只处理 .cs 文件(不区分大小写)
- if !d.IsDir() && strings.EqualFold(filepath.Ext(path), ".cs") {
- hasBOM, err := checkUTF8WithBOM(path)
- if err != nil {
- fmt.Fprintf(os.Stderr, "Warning: cannot read file %s: %v\n", path, err)
- return nil
- }
- if !hasBOM {
- if true {
- // 写入模式:转换文件
- if err := convertToUTF8WithBOM(path, false); err != nil {
- fmt.Fprintf(os.Stderr, "Error converting %s: %v\n", path, err)
- } else {
- fmt.Printf("Converted: %s\n", path)
- }
- } else {
- // 只读模式:仅输出路径
- fmt.Println(path)
- }
- }
- }
- return nil
- })
- if err != nil {
- fmt.Fprintf(os.Stderr, "Error walking directory: %v\n", err)
- os.Exit(1)
- }
- }
- // 自定义字符串 slice 类型的 flag,支持多次使用
- type stringSliceFlag []string
- func (s *stringSliceFlag) String() string {
- return strings.Join(*s, ",")
- }
- func (s *stringSliceFlag) Set(value string) error {
- *s = append(*s, value)
- return nil
- }
- // checkUTF8WithBOM 检查文件是否以 UTF-8 BOM 开头
- func checkUTF8WithBOM(filename string) (bool, error) {
- file, err := os.Open(filename)
- if err != nil {
- return false, fmt.Errorf("failed to open file: %w", err)
- }
- defer file.Close()
- bom := make([]byte, 3)
- n, err := file.Read(bom)
- if err != nil && err.Error() != "EOF" {
- return false, fmt.Errorf("failed to read file: %w", err)
- }
- if n < 3 {
- return false, nil
- }
- return string(bom) == utf8BOMPrefix, nil
- }
- // 将文件转换为 UTF-8 with BOM
- func convertToUTF8WithBOM(filename string, backup bool) error {
- // 读取原始文件内容
- content, err := os.ReadFile(filename)
- if err != nil {
- return fmt.Errorf("failed to read file: %w", err)
- }
- // 如果文件已经是 UTF-8 with BOM,跳过
- if len(content) >= 3 && string(content[:3]) == utf8BOMPrefix {
- return nil
- }
- // 如果需要备份,创建备份文件
- if backup {
- backupFile := filename + ".bak"
- if err := os.WriteFile(backupFile, content, 0644); err != nil {
- return fmt.Errorf("failed to create backup: %w", err)
- }
- }
- // 创建临时文件
- tempFile := filename + ".tmp"
- file, err := os.Create(tempFile)
- if err != nil {
- return fmt.Errorf("failed to create temp file: %w", err)
- }
- // 写入 BOM
- if _, err := file.WriteString(utf8BOMPrefix); err != nil {
- file.Close()
- os.Remove(tempFile)
- return fmt.Errorf("failed to write BOM: %w", err)
- }
- // 写入原始内容
- if _, err := file.Write(content); err != nil {
- file.Close()
- os.Remove(tempFile)
- return fmt.Errorf("failed to write content: %w", err)
- }
- file.Close()
- // 替换原文件
- if err := os.Rename(tempFile, filename); err != nil {
- // 如果重命名失败,尝试删除原文件再重命名
- os.Remove(filename)
- if err := os.Rename(tempFile, filename); err != nil {
- return fmt.Errorf("failed to replace original file: %w", err)
- }
- }
- return nil
- }
|