跨系统文件乱码解决方案

不得不再次感叹一句 “DeepSeek 大法好啊”,极大的节省了查资料和验证结果的时间,很快就解决了遇到的问题。
当我一筹莫展不知如何下手时,在解决 hexo 发布报错的问题时,看到了其他博客中的跨系统文件导致的无法发布 hexo 博客的例子,突然明白如何给 AI 描述我当前遇到的问题了。

歪楼,hexo 无法上传到原因是我使用了代理,导致 git 无法连接远程 ssh 导致的。

回归正题,当我没有代理时,只能使用百度进行搜索,当然搜的前排都是 CSDN 乱七八糟的解决方案,并不是我要的,此时我想到了废物豆包,试了一下它给的方案,结果可想而知,根本用不了。

好在,百度接了DeepSeek满血版,我又可以了。

我的愚蠢在于我基于豆包的方案去问 DeepSeek,而不是让 DeepSeek 给我一个新方案。所以中间还是浪费了一些时间去验证豆包的愚蠢方案。

问题背景

当我直接压缩打包项目文件通过微信文件传输从 mac 系统传到 windows 系统上时,因为系统编码方式不同导致文件目录在 windows 系统下显示成了 乱码。

问题原因‌

不同系统默认编码不同:

Windows 中文系统‌:默认使用 GBK/GB2312 编码。
Linux/macOS‌:默认使用 UTF-8 编码。
若文件名含非 ASCII 字符(如中文),跨系统复制时未统一编码会导致乱码。

假设乱码文件原本是 GBK 编码,但在其他系统被错误解析为 UTF-8。例如:

原文件名(GBK):中文目录
乱码显示(UTF-8):涓枃鐩綍

解决方案‌(初步)

在多系统(如 Windows/Linux/macOS)之间传递文件时,若因编码不一致导致目录或文件名出现乱码,可以通过以下步骤使用命令行工具修复编码(以 Windows 系统为例):

通过命令行检测原始编码(如 GBK),将文件名和目录名从 GBK 转换为 UTF-8,再重新命名。

以下是针对 macOS 到 Windows 文件传输导致文件名乱码场景的 ‌强化版 PowerShell 脚本‌,已集成路径冲突检测和容错机制:


# 文件名修复脚本(macOS → Windows 乱码修复)
# 保存为 fix_macos_to_win_encoding.ps1,右键管理员身份运行

# 配置参数
$sourcePath = "C:\乱码目录"  # 需修改为实际路径
$originalEncoding = [System.Text.Encoding]::UTF8  # macOS 使用 UTF-8
$targetEncoding = [System.Text.Encoding]::GetEncoding("GBK")  # Windows 默认 GBK
$logFile = Join-Path $sourcePath "rename_log.txt"  # 日志文件路径

# 初始化日志
"开始时间: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')" | Out-File $logFile -Encoding UTF8
"正在处理目录: $sourcePath" | Out-File $logFile -Append

# 递归处理所有文件和目录(按深度倒序,先处理子项)
Get-ChildItem -Path $sourcePath -Recurse | Sort-Object -Property FullName -Descending | ForEach-Object {
    $currentItem = $_
    try {
        # 将乱码名称按错误解析的字节还原正确名称
        $rawBytes = $targetEncoding.GetBytes($currentItem.Name)
        $correctName = $originalEncoding.GetString($rawBytes)

        # 检测名称是否已正确或无需修改
        if ($correctName -eq $currentItem.Name) {
            Write-Host "[跳过] 名称无需修改: $($currentItem.FullName)"
            "[跳过] $($currentItem.FullName)" | Out-File $logFile -Append
            return  # 跳过当前项
        }

        # 检测目标路径是否存在同名文件
        $newPath = Join-Path $currentItem.Directory.FullName $correctName
        if (Test-Path $newPath) {
            Write-Host "[冲突] 目标已存在: $newPath"
            "[冲突] $newPath" | Out-File $logFile -Append
            return  # 跳过冲突项
        }

        # 执行重命名
        Rename-Item -Path $currentItem.FullName -NewName $correctName -Force -ErrorAction Stop
        Write-Host "[成功] 重命名: $($currentItem.Name)$correctName"
        "[成功] $($currentItem.FullName)$correctName" | Out-File $logFile -Append
    }
    catch {
        Write-Host "[失败] 错误: $_"
        "[失败] $($currentItem.FullName) → 错误: $_" | Out-File $logFile -Append
    }
}

# 完成提示
Write-Host "`n处理完成!日志已保存至: $logFile"

关键优化点说明‌

冲突路径检测‌

名称无变化跳过‌:通过 if ($correctName -eq $currentItem.Name) 直接跳过无需修改的文件,避免触发 源路径和目标路径必须不同 错误。
目标路径存在性检查‌:使用 Test-Path $newPath 检测目标是否已存在同名文件,避免覆盖冲突。

日志记录‌

记录所有操作(成功/跳过/冲突/失败)到 rename_log.txt,便于后续排查。
日志文件使用 UTF-8 编码保存,避免乱码。

错误处理‌

使用 try-catch 捕获异常,防止脚本因单个文件错误中断。
强制 -ErrorAction Stop 确保错误能被捕获。

递归处理优化‌

保持 Sort-Object -Descending 确保先处理深层文件,避免父目录更名后子项路径失效。
使用场景示例‌

假设 macOS 传输到 Windows 的文件名 文档.txt 因编码问题显示为乱码 鏂囨。.txt,脚本会将其还原为正确名称:

# 乱码名称解码流程
$rawBytes = [System.Text.Encoding]::GetEncoding("GBK").GetBytes("鏂囨。.txt")
$correctName = [System.Text.Encoding]::UTF8.GetString($rawBytes)  # 输出 "文档.txt"

注意事项‌

管理员权限‌:需以管理员身份运行脚本,否则可能因权限不足无法修改系统文件。

备份数据‌:操作前备份重要文件,防止意外损坏。

编码适配‌:若仍有部分乱码,尝试调整 $originalEncoding 或 $targetEncoding(如 Big5 或 Shift-JIS)。

扩展名处理‌:若文件扩展名被隐藏,需在脚本中显式处理(如强制添加 .txt 后缀)。
扩展调试建议‌

单文件测试‌:修改 $sourcePath 为单个文件路径,验证脚本逻辑。

编码探测‌:使用 file -i 文件名(Linux/macOS)或第三方工具(如 EncodingChecker)确定原始编码。

手动修正‌:对于少量文件,可用 chcp 65001 临时启用 UTF-8 命令行环境,直接重命名。

通过此脚本,可系统性解决 macOS 到 Windows 文件名乱码问题,同时规避路径冲突风险。

进一步解决文件问题

问题分析‌

当目录结构修复后,部分 .md 文件仍存在乱码,可能原因如下:

混合编码干扰‌:文件名中某些字符的编码格式与预期不符(如部分字符来自其他编码标准)。
冲突跳过‌:原脚本检测到目标路径已存在同名文件,未执行重命名。
特殊符号处理‌:文件名包含 #, & 等符号,导致编码转换异常。

解决方案‌

方法一:针对 .md 文件增强修复脚本‌

修改原脚本,‌仅处理 .md 文件‌并优化编码转换逻辑:


# 增强版脚本:修复残留的 .md 文件名乱码
$sourcePath = "C:\已修复目录"  # 修改为实际路径
$originalEncoding = [System.Text.Encoding]::UTF8
$targetEncoding = [System.Text.Encoding]::GetEncoding("GBK")

Get-ChildItem -Path $sourcePath -Recurse -Filter *.md | ForEach-Object {
    $currentItem = $_
    try {
        # 尝试多种编码转换组合(UTF-8 → GBK 或反向)
        $rawBytes = $targetEncoding.GetBytes($currentItem.BaseName)  # 仅处理文件名(不含扩展名)
        $correctBaseName = $originalEncoding.GetString($rawBytes)
        $correctName = "$correctBaseName.md"  # 强制保留 .md 扩展名

        # 如果直接转换无效,尝试反向操作(GBK → UTF-8)
        if ($correctName -eq $currentItem.Name) {
            $rawBytes = $originalEncoding.GetBytes($currentItem.BaseName)
            $correctBaseName = $targetEncoding.GetString($rawBytes)
            $correctName = "$correctBaseName.md"
        }

        # 检测是否需要修改
        if ($correctName -eq $currentItem.Name) {
            Write-Host "[跳过] 名称无需修改: $($currentItem.FullName)"
            return
        }

        # 执行重命名
        Rename-Item -Path $currentItem.FullName -NewName $correctName -Force
        Write-Host "[成功] 已修复: $($currentItem.Name)$correctName"
    }
    catch {
        Write-Host "[失败] 错误: $_"
    }
}
关键优化‌:

限定 -Filter *.md 仅处理 Markdown 文件。
双向尝试编码转换(UTF-8 ↔ GBK),覆盖更多异常情况。
强制保留 .md 扩展名,避免误删。

方法二:手动修正个别文件‌

若文件数量较少,可直接通过 ‌资源管理器‌ 或 ‌PowerShell 命令‌ 重命名:

显示文件扩展名‌(避免误操作):


Set-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" -Name "HideFileExt" -Value 0
Stop-Process -Name explorer  # 重启资源管理器生效

手动重命名‌:


# 示例:将乱码文件 "鏂囨。.md" 改为 "文档.md"
Rename-Item -Path "C:\已修复目录\鏂囨。.md" -NewName "文档.md"

方法三:使用第三方工具批量修正‌

借助工具自动检测编码并重命名:

工具推荐‌:

Ant Renamer(免费开源,支持编码转换)
Bulk Rename Utility(高级批量重命名功能)
操作流程‌:
导入目标 .md 文件。
选择 “Encoding” 或 “Replace” 功能,设置 UTF-8 → GBK 转换规则。
预览更改后执行批量重命名。

排查与验证‌

检查日志文件‌:
查看原脚本生成的 rename_log.txt,定位被跳过的文件及原因。

编码探测‌:

用以下命令检查文件名的实际字节编码(需安装 Python):


# 分析文件名 "鏂囨。.md" 的真实编码
python -c "print('鏂囨。.md'.encode('gbk'))"  # 输出 b'...' 格式的字节流
内容乱码修复‌:

若文件内容也有乱码,使用 VS Code 或 Notepad++ 手动切换编码(UTF-8/GBK)。

注意事项‌

备份优先‌:操作前复制目标目录,防止误操作导致数据丢失。
权限问题‌:以管理员身份运行脚本或工具,确保有权修改系统文件。
扩展名一致性‌:确保重命名时保留 .md 扩展名,避免文件失效。

通过上述方法,可彻底解决残留的 Markdown 文件名乱码问题。

以上就是 AI 的解决方案,完美解决了我的问题,不过答案不是一次性就写的这么完整的,需要不断的提供报错信息和预期不符的地方进行调整。