基于文件头的二进制标志识别。检测到人工桌面的视频头(开头有00 00的)自动删除头恢复成视频,检测到图片特征自动重命名补全扩展名。

以下内容存为bat文件即可开始使用。修复后的文件和bat自身同目录。

单文件转换:双击bat,并拖入一个需要恢复成正常文件的.ndf资源文件
多文件转换:大量.ndf资源文件拖拽到刚才创建的bat文件图标上(一次不要太多)

<# :
@echo off
setlocal

:: 1. 输入路径预处理
if "%~1"=="" (
    echo [INFO] 请拖入文件或粘贴路径:
    set /p "MY_INPUT_PATHS=路径: "
) else (
    set "MY_INPUT_PATHS=%*"
)

:: 2. 环境上下文
set "MY_BAT_DIR=%~dp0"

:: 3. 调用 PowerShell 内核执行逻辑
powershell -NoProfile -ExecutionPolicy Bypass -Command "IEX ([System.IO.File]::ReadAllLines('%~f0', [System.Text.Encoding]::Default) -join [Environment]::NewLine)"

echo.
echo ----------------------------------------------------------
echo [状态] 任务处理序列已完成。
pause
exit /b
#>

# 从环境变量获取数据
$rawInput = $env:MY_INPUT_PATHS
$targetDir = $env:MY_BAT_DIR
if (-not $rawInput) { exit }

# ============================================================
# 维护字典:多媒体特征码数据库 (格式: ".后缀" = @(偏移量, 字节序列))
# ============================================================
$Signatures = @{
    ".mp4"  = @(4, 0x66, 0x74, 0x79, 0x70) # ftyp 标识
    ".jpg"  = @(0, 0xFF, 0xD8)             # JPEG 起始符
    ".png"  = @(0, 0x89, 0x50, 0x4E, 0x47) # PNG 标识
    ".gif"  = @(0, 0x47, 0x49, 0x46)       # GIF 标识
    ".bmp"  = @(0, 0x42, 0x4D)             # Windows 位图标识
    ".webp" = @(8, 0x57, 0x45, 0x42, 0x50) # WEBP 容器标识
}

# 解析输入路径并过滤空项
$pathList = [regex]::Matches($rawInput, '(?<=")[^"]+(?=")|[^\s"]+') | ForEach-Object { $_.Value } | Where-Object { -not [string]::IsNullOrWhiteSpace($_) }

foreach ($sourcePath in $pathList) {
    $sourcePath = $sourcePath.Trim()
    if (-not (Test-Path $sourcePath -PathType Leaf)) { continue }
    
    $fileStream = $null
    try {
        # 以只读模式打开源文件流
        $fileStream = [System.IO.File]::OpenRead($sourcePath)
        if ($fileStream.Length -lt 16) { $fileStream.Close(); continue }

        # 读取头部 16 字节缓冲区
        $buffer = New-Object byte[] 16
        [void]$fileStream.Read($buffer, 0, 16)
        
        # 1. 检测特定冗余头 (00 00) 并确定全局逻辑偏移
        $logicOffset = if ($buffer[0] -eq 0 -and $buffer[1] -eq 0) { 2 } else { 0 }
        $isRepairNeeded = ($logicOffset -eq 2)

        # 2. 匹配特征库确定目标后缀
        $detectedExt = ".dat"
        foreach ($entry in $Signatures.GetEnumerator()) {
            $extKey = $entry.Name
            $sigPos = $entry.Value[0]
            $sigBytes = $entry.Value[1..($entry.Value.Count-1)]
            
            $isMatch = $true
            for ($i = 0; $i -lt $sigBytes.Count; $i++) {
                if ($buffer[$logicOffset + $sigPos + $i] -ne $sigBytes[$i]) {
                    $isMatch = $false; break
                }
            }
            if ($isMatch) { $detectedExt = $extKey; break }
        }

        # 3. 构造输出物理路径
        $fileNameNoExt = [System.IO.Path]::GetFileNameWithoutExtension($sourcePath)
        $outputFilePath = [System.IO.Path]::Combine($targetDir, ($fileNameNoExt + $detectedExt))
        
        # 4. 执行物理持久化操作
        if ($isRepairNeeded) {
            # 修复逻辑:跳过冗余头并写入新文件
            Write-Host "[REPAIR] $detectedExt : $(Split-Path $sourcePath -Leaf)" -ForegroundColor Green
            $destStream = [System.IO.File]::Create($outputFilePath)
            [void]$fileStream.Seek(2, [System.IO.SeekOrigin]::Begin)
            $fileStream.CopyTo($destStream)
            $destStream.Close()
        } else {
            # 识别逻辑:归拢副本至脚本目录
            $fileStream.Close()
            $sourceFullName = (Get-Item $sourcePath).FullName
            if ($sourceFullName -ne $outputFilePath) {
                Copy-Item $sourcePath -Destination $outputFilePath -Force
                Write-Host "[IDENTY] $detectedExt : $(Split-Path $sourcePath -Leaf)" -ForegroundColor Cyan
            }
        }
    } catch { 
        Write-Host "[ERROR] 无法处理文件: $sourcePath" -ForegroundColor Red 
    } finally { 
        if ($fileStream) { $fileStream.Close() } 
    }
}