FErD 发表于 2024-5-11 06:24:43

游戏盘被 VN 爆破后如何科学节约储存空间 硬链接兼用版

本帖最后由 FErD 于 2024-6-27 17:29 编辑



下载

这一版与之前的不同,对硬链接使用了winrar的rar5专有格式而非7zip的tar格式进行压缩,
相比较体积更小,但需要额外指定winrar命令行模式的可执行程序位置。
修复了Game_Clean删文件的bug

请自行按自己的习惯修改,用脚本转化.ps1可将其转化为exe执行文件









使用指南



运行前的文件目录结构,
可自行在用户变量内修改

运行后的文件目录结构,
可自行在用户变量内修改




#游戏文件夹名字
$GamefileName

      #nodvd游戏 iso文件放置位置
      Runtime

      #安装文件
      Install
      #附加内容,建议拆了入库(图库 音乐库 漫画库等)
      Extra

      #游戏本体
      *JPN*
      *CHI*
      *ENG*
      $GamefileName*
      





#游戏文件夹名字
$GamefileName

      #nodvd游戏 iso文件放置位置
      Runtime

      #安装文件
      $GamefileName-Install.7z
      #附加内容,建议拆了入库(图库 音乐库 漫画库等)
      $GamefileName-Extra.7z

      #游戏本体
      $GamefileName.7z|rar
      #对游戏本体而言的差别,比如存档
      $GamefileName-updata.7z
                        






使用指南



运行前的文件目录结构,
可自行在用户变量内修改

运行后的文件目录结构,
可自行在用户变量内修改




#游戏文件夹名字
$GamefileName

      #nodvd游戏 iso文件放置位置
      Runtime

      #安装文件
      Install
      #附加内容,建议拆了入库(图库 音乐库 漫画库等)
      Extra

      #游戏本体
      *JPN*
      *CHI*
      *ENG*
      $GamefileName*
      





#游戏文件夹名字
$GamefileName

      #nodvd游戏 iso文件放置位置
      Runtime

      #安装文件
      $GamefileName-Install.7z
      #附加内容,建议拆了入库(图库 音乐库 漫画库等)
      $GamefileName-Extra.7z

      #游戏本体
      $GamefileName.7z|$GamefileName.tar
      #对游戏本体而言的差别,比如存档
      $GamefileName-updata.7z
                        
      




上一版

游戏盘被VN爆破后如何科学节约储存空间
https://www.gamemale.com/forum.p ... 4382&fromuid=668102
(出处: GameMale)
大概压出了50g(


上一稿修修改改对硬链接支持不太好。
加了挺多行(答辩山越来越高了)
(主要是给黑奴ai提需求造出来了一堆模块,写好逻辑放了进去)
(ai推荐用函数,但powershell和7zip好像攻受不合)

这一版对仓鼠,日文 中文 英文各存一份,或者中+原文一份的优化量比上一版会好巨多。
建议相配合查重软件查重后进行硬链接。

用户变量
如有自定义需求请对照P1进行自定义。



# 设置 7-Zip 可执行文件的路径
$7zipPath = "B:\program\7-Zip\7z.exe"

# 创建 7-Zip 命令的别名
Set-Alias Expand-7Zip $7zipPath
Set-Alias Compress-7Zip $7zipPath
#7Zip最好不要用设定文件名的变量

# 获取当前工作目录的完整路径
$GameFilePath = Get-Location
# 提取当前路径的文件夹名称
$GameFolderName = Split-Path -Path $GameFilePath -Leaf

#设定文件名
$GameFile = "$GameFolderName"
$GameFileUpdata = "$GameFolderName-updata"
$GameFileInstall = "$GameFolderName-Install"
$GameFileExtra = "$GameFolderName-Extra"

#temp ssd路径
$TempssdFolder = "Y:\temp\game\$GameFolderName"

# 转换排除项为 7-Zip 排除参数
$7zipExclusions = @(
    "ReadyRunGame_linktemp.exe",
    "ReadyCloseGame_linktemp.exe",
    "ReadyRunGame_runtime.exe",
    "ReadyCloseGame_runtime.exe",
    "Game_Clean.exe",
    "UserVar.ps1",

    "$GameFileInstall.7z",
    "Install",
    "Install\*",
    "$GameFileRuntime.7z",
    "Runtime",
    "Runtime\*",
    "$GameFileExtra.7z",
    "Extra",
    "Extra\*"
)
$7zipExclusionParams = $7zipExclusions | ForEach-Object { "-x!$_" }


ReadyRunGame

. "$PWD\UserVar.ps1"

#挂载无nodisk补丁游戏运行文件

#文件在Runtime挂载
#游戏的nodisk补丁无用时使用

if (Test-Path "$PWD\Runtime") {
Start-Process "$PWD\ReadyRunGame_runtime.exe" -Wait
}
else {
# 如果 "$PWD\Runtime" 路径不存在,则可以在这里添加其他操作
}

#解压

# 检查 $GameFolderName.* 文件是否存在
if (Test-Path "$PWD\$GameFile.*") {
    # 如果$GameFile文件存在 检查 $GameFolderName-update.7z 文件是否存在
    if (Test-Path "$PWD\$GameFile.7z") {
      Expand-7Zip x "$PWD\$GameFile.7z" -o"$TempssdFolder" -aoa
    }
    if (Test-Path "$PWD\$GameFile.tar") {
      Expand-7Zip x "$PWD\$GameFile.tar" -o"$TempssdFolder" -aoa
      #创建SHA256表
      {
      # 创建一个空的哈希表来存储文件路径和对应的哈希值
      $hashTable = @{}
      # 获取目录 A 中所有文件的列表
      $files = Get-ChildItem -Path "$TempssdFolder" -Recurse
      # 遍历文件列表,计算每个文件的 SHA256 哈希值
      foreach ($file in $files) {
            if (!$file.PSIsContainer) {
                $hash = (Get-FileHash -Path $file.FullName -Algorithm SHA256).Hash
                # 将文件的相对路径和哈希值添加到哈希表中
                $relativePath = $file.FullName.Substring($TempssdFolder.Length + 1)
                $hashTable[$relativePath] = $hash
            }
      }
      # 将哈希表中的内容转换为字符串,并保存到 fileA.txt
      $hashTableString = $hashTable.GetEnumerator() | ForEach-Object { "$($_.Key)=$($_.Value)" }
      $hashTableString | Out-File "$TempssdFolder.txt" -Encoding UTF8
      }
    }
    if (Test-Path "$PWD\$GameFileUpdata.7z") {
      Expand-7Zip x "$PWD\$GameFileUpdata.7z" -o"$TempssdFolder" -aoa
    }
} else {    }

#软连接
{
# 获取源目录根下的所有文件夹和文件
$TempssdFolderitems = Get-ChildItem -Path $TempssdFolder -Name
    # 为每个文件或文件夹创建软链接
foreach ($TempssdFolderitem in $TempssdFolderitems) {
    $GameFolderlink = Join-Path -Path $PWD -ChildPath $TempssdFolderitem
    $TempssdFoldertarget = Join-Path -Path $TempssdFolder -ChildPath $TempssdFolderitem
    New-Item -ItemType SymbolicLink -Path $GameFolderlink -Target $TempssdFoldertarget
}}


ReadyRunGame_runtime

nodvd的游戏内部的游戏数据文件是可删的,一般安装位置如果存在这些文件就没有问题
bin光盘映像建议转化iso后另存为,转载后可解决游戏不识别的问题。


. "$PWD\UserVar.ps1"

#挂载无nodisk补丁游戏运行文件

#文件在Runtime挂载
#游戏的nodisk补丁无用时使用

if (Test-Path "$PWD\Runtime") {
    Start-Process "$PWD\ReadyRunGame_runtime.exe" -Wait
} else {
# 如果 "$PWD\Runtime" 路径不存在,则可以在这里添加其他操作
}

#解压

# 检查 $GameFolderName.* 文件是否存在
if ((Test-Path "$PWD\${GameFile}.7z") -or (Test-Path "$PWD\${GameFile}.tar")) {
    # 如果$GameFile文件存在 检查 $GameFolderName-update.7z 文件是否存在
    if (Test-Path "$PWD\${GameFile}.7z") {
      Expand-7Zip x "$PWD\${GameFile}.7z" -o"$TempssdFolder" -aoa
    }
    if (Test-Path "$PWD\${GameFile}.tar") {
      Expand-7Zip x "$PWD\${GameFile}.tar" -o"$TempssdFolder" -aoa
      #创建SHA256表
      $hashTable = @{}
      # 获取目录 A 中所有文件的列表
      $files = Get-ChildItem -Path "$TempssdFolder" -Recurse
      # 遍历文件列表,计算每个文件的 SHA256 哈希值
      foreach ($file in $files) {
            if (!$file.PSIsContainer) {
                $hash = (Get-FileHash -Path $file.FullName -Algorithm SHA256).Hash
                # 将文件的相对路径和哈希值添加到哈希表中
                $relativePath = $file.FullName.Substring($TempssdFolder.Length + 1)
                $hashTable[$relativePath] = $hash
            }
      }
      # 将哈希表中的内容转换为字符串,并保存到 fileA.txt
      $hashTableString = $hashTable.GetEnumerator() | ForEach-Object { "$($_.Key)=$($_.Value)" }
      $hashTableString | Out-File "$TempssdFolder.txt" -Encoding UTF8
      }
    if (Test-Path "$PWD\${GameFileUpdata}.7z") {
      Expand-7Zip x "$PWD\${GameFileUpdata}.7z" -o"$TempssdFolder" -aoa
    }
} else {    }

# 创建软链接
if (Test-Path "$TempssdFolder") {
# 获取源目录根下的所有文件夹和文件
$TempssdFolderitems = Get-ChildItem -Path $TempssdFolder -Name
    # 为每个文件或文件夹创建软链接
foreach ($TempssdFolderitem in $TempssdFolderitems) {
    $GameFolderlink = Join-Path -Path $PWD -ChildPath $TempssdFolderitem
    $TempssdFoldertarget = Join-Path -Path $TempssdFolder -ChildPath $TempssdFolderitem
    New-Item -ItemType SymbolicLink -Path $GameFolderlink -Target $TempssdFoldertarget
}}




ReadyCloseGame_linktemp

改动最大的部分。
匹配游戏本体目录中,如果重复出现2个于2个以上则使用tar模式压缩
如果需要自动硬链接也能自行添加在这一部分
(在139行之前加这个功能,具体写法可用要求bingai)
    Compress-7Zip a "$PWD\$GameFile.tar" "$PWD\*" -mx=9 -snh -snl @7zipExclusionParams

咒语参考
如何使用PS1脚本编写以下命令
计算目录A中文件的sha256,保存到文件A。
比较文件A中的计算记录,只有当文件的文件名、文件大小与sha256均相同的情况下,将这些全部相同的文件进行硬链接。

硬链接的tar文件用更新模式有很多奇奇怪怪的问题,包括但不限于重复压缩 文字乱码 硬链接失效等,
powershell自带的比7zip的更吓人。
最后用的查重删除命令解决的,




. "$PWD\UserVar.ps1"

#Runtime 卸载
#游戏的 nodisk 补丁无用时使用
if (Test-Path "$PWD\Runtime") {
Start-Process "$PWD\ReadyCloseGame_runtime.exe" -Wait
}else {
# 如果 "$PWD\Runtime" 路径不存在,则可以在这里添加其他操作
}

#安装文件压缩
if (Test-Path "$PWD\Install") {
    if (Test-Path "$PWD\${GameFileInstall}.7z") {
    # 等待用户按下任意键
    $null = Read-Host "存在 Install 目录与 Install 压缩包,你最好检查一下"
    } else {
    Compress-7Zip a "$PWD\${GameFileInstall}.7z" "$PWD\Install\*" -mx=9 -m0=LZMA2 -snh -snl -md=256m -ms=on -mfb=273 -mmc=10000000 -bsp1
    Remove-Item "$PWD\Install" -Recurse -Force
    }
} else {
# 继续执行脚本的其他部分
}

#Extra 文件压缩
if (Test-Path "$PWD\Extra") {
    if (Test-Path "$PWD\${GameFileExtra}.7z") {
    # 等待用户按下任意键
    $null = Read-Host "存在 Extra 目录与 Extra 压缩包,你最好检查一下,将其分别入库"
    } else {
    Compress-7Zip a "$PWD\${GameFileExtra}.7z" "$PWD\Extra\*" -mx=9 -m0=LZMA2 -snh -snl -md=256m -ms=on -mfb=273 -mmc=10000000 -bsp1
    Remove-Item "$PWD\Extra" -Recurse -Force
    }
} else {
# 继续执行脚本的其他部分
}

#游戏文件压缩

# 如果 "$PWD\$GameFile" 文件存在
if ((Test-Path "$PWD\${GameFile}.7z") -or (Test-Path "$PWD\${GameFile}.tar")) {
    # 如果 "$PWD\${GameFile}.7z" 文件存在
    if (Test-Path "$PWD\${GameFile}.7z") {
      # 如果 ${GameFileUpdata}.7z 文件存在
      if (Test-Path "$PWD\${GameFileUpdata}.7z") {
            # 删除 ${GameFileUpdata}.7z 文件
            Remove-Item "$PWD\${GameFileUpdata}.7z" -Recurse -Force
      }
            # 使用更新模式将对象添加到 ${GameFile}.7z
      Compress-7Zip u "$PWD\${GameFile}.7z" "$TempssdFolder\*" -mx9 -u- -up0q3x2z0!GameUpdatasave @7zipExclusionParams
      Rename-Item -Path "$PWD\GameUpdatasave.7z" -NewName "${GameFileUpdata}.7z"
      }
    # 如果 "$PWD\${GameFile}.tar" 文件存在
    if (Test-Path "$PWD\${GameFile}.tar") {
      # 创建 SHA256 表
      $hashTable = @{}
      # 获取目录 A 中所有文件的列表
      $files = Get-ChildItem -Path "$TempssdFolder" -Recurse
      # 遍历文件列表,计算每个文件的 SHA256 哈希值
      foreach ($file in $files) {
            if (!$file.PSIsContainer) {
                $hash = (Get-FileHash -Path $file.FullName -Algorithm SHA256).Hash
                # 将文件的相对路径和哈希值添加到哈希表中
                $relativePath = $file.FullName.Substring($TempssdFolder.Length + 1)
                $hashTable[$relativePath] = $hash
            }
      }
      # 将哈希表中的内容转换为字符串,并保存到 fileA.txt
      $hashTableString = $hashTable.GetEnumerator() | ForEach-Object { "$($_.Key)=$($_.Value)" }
      $hashTableString | Out-File "$TempssdFolder-Updata.txt" -Encoding UTF8
      
      # 从文件 A 和文件 B 中读取比较哈希值,并删除匹配的文件
      # 从文件 A 和文件 B 中读取哈希值和相关信息
      $hashInfoA = Get-Content "${TempssdFolder}.txt" -Raw | ConvertFrom-StringData
      $hashInfoB = Get-Content "${TempssdFolder}-Updata.txt" -Raw | ConvertFrom-StringData
      
      # 比较文件 A 和文件 B 中记录的哈希值,并删除匹配的文件
      foreach ($key in $hashInfoA.Keys) {
            if ($hashInfoB.ContainsKey($key) -and $hashInfoA[$key] -eq $hashInfoB[$key]) {
                $fileToDelete = Join-Path "$TempssdFolder" $key
                if (Test-Path $fileToDelete) {
                  Remove-Item $fileToDelete -Force
                  Write-Host "已删除文件: $fileToDelete"
                } else {
                  Write-Host "未找到文件: $fileToDelete"
                }
            }
      }
      if (Test-Path "$PWD\${GameFileUpdata}.7z") {
      # 如果文件存在,则删除 ${GameFileUpdata}.tar 文件
      Remove-Item "$PWD\${GameFileUpdata}.7z" -Recurse -Force
      }
      Compress-7Zip a "$PWD\${GameFileUpdata}.7z" "$TempssdFolder\*" -mx=9 -m0=LZMA2 -snh -snl -md=256m -ms=on -mfb=273 -mmc=10000000 -bsp1 @7zipExclusionParams
    }
    #删除主目录的软连接
    # 获取目录 A 中的所有项
    $itemsInDirectoryGame = Get-ChildItem -Path "$PWD"
    # 遍历目录 A 中的每个项
    foreach ($item in $itemsInDirectoryGame) {
      # 检查是否为软链接
      if ($item.Attributes -band ::ReparsePoint) {
                # 删除软链接
                Remove-Item -Path $item.FullName -Recurse -Force
            }    }
    #清理 temp
    Remove-Item -Path "$TempssdFolder" -Recurse -Force
    Remove-Item -Path "${TempssdFolder}.txt" -Recurse -Force
    Remove-Item -Path "${TempssdFolder}-Updata.txt" -Recurse -Force
   

    } else {
    # 如果文件不存在,使用创建 $GameFile 文件
    # 定义要匹配的文件夹模式
    $GameFolderTest = @(
      "*CHI*",
      "*ENG*",
      "*JPN*",
      "*$GameFile*"
      )
    # 获取匹配模式的文件夹列表
    $GameFolderTestList = Get-ChildItem -Path $PWD -Recurse -Directory | Where-Object {
      foreach ($pattern in $GameFolderTest) {
            if ($_.Name -like $pattern) {
                return $true
            }
      }
      return $false
      }
    if ($GameFolderTestList.Count -ge 2) {
    Compress-7Zip a "$PWD\${GameFile}.tar" "$PWD\*" -mx=9 -snh -snl @7zipExclusionParams
    }
    if ($GameFolderTestList.Count -eq 1) {
    Compress-7Zip a "$PWD\${GameFile}.7z" "$PWD\*" -mx=9 -m0=LZMA2 -snh -snl -md=256m -ms=on -mfb=273 -mmc=10000000 -bsp1 @7zipExclusionParams
    }
}



#清理主目录
if ((Test-Path "$PWD\${GameFile}.7z") -or (Test-Path "$PWD\${GameFile}.tar")) {
# 定义要排除的文件和文件夹模式数组
$delitemsToExclude = @(
"$PWD\*.iso",
"$PWD\${GameFile}.*", "$PWD\${GameFileUpdata}.*", "$PWD\${GameFileInstall}.*",
"$PWD\ReadyRunGame_linktemp.exe", "$PWD\ReadyCloseGame_linktemp.exe", "$PWD\ReadyRunGame_runtime.exe", "$PWD\ReadyCloseGame_runtime.exe", "$PWD\UserVar.ps1", "$PWD\Game_Clean.exe"
"$PWD\Runtime", "$PWD\Runtime\*", "$PWD\Install", "$PWD\Install\*", "$PWD\Extra", "$PWD\Extra\*"
)

$delitemsToRemove = Get-ChildItem -Path $PWD -Recurse | Where-Object {
    $exclude = $false
    foreach ($delpattern in $delitemsToExclude) {
      if ($_.FullName -like $delpattern) {
            $exclude = $true
            break
      }
    }
    -not $exclude # 如果没有匹配任何排除模式,则选择该项
}

# 检查每个项是否存在,然后删除
foreach ($delitem in $delitemsToRemove) {
    if (Test-Path $delitem.FullName) {
      Remove-Item $delitem.FullName -Recurse -Force
    }
}
}

Start-Process "$PWD\Game_Clean.exe"




ReadyCloseGame_runtime

# 导入变量
. "$PWD\UserVar.ps1"

# 定义要匹配的文件模式数组
$GameRuntimeitemsToInclude = @("$PWD\Runtime\*.iso")

# 获取 Runtime 文件夹中所有文件,并只选择匹配的文件模式
$GameRuntimeitemsToRuntimePath = Get-ChildItem -Path "$PWD\Runtime" -Recurse | Where-Object {
    foreach ($GameRuntimepattern in $GameRuntimeitemsToInclude) {
      if ($_.FullName -like $GameRuntimepattern) {
            return $true # 如果匹配包含模式,则选择该项
      }
    }
    return $false # 如果没有匹配任何包含模式,则不选择该项
}

# 挂载匹配的磁盘映像
foreach ($GameRuntimeitem in $GameRuntimeitemsToRuntimePath) {
    if (Test-Path $GameRuntimeitem.FullName) {
      Dismount-DiskImage -ImagePath $GameRuntimeitem.FullName
    }
}

# 检查特定路径的程序是否正在运行
$exePath = "$PWD\ReadyCloseGame_linktemp.exe"
$processes = Get-WmiObject Win32_Process | Select-Object ExecutablePath
$running = $processes | Where-Object { $_.ExecutablePath -eq $exePath }

if ($running) {
    # 如果程序正在运行
    # 在这里添加您想要执行的操作
} else {
    # 如果程序未运行
    Start-Process -FilePath "$PWD\Game_Clean.exe"
}





放到设置的全局脚本里面

$PlayniteInstallDir = $PlayniteApi.ExpandGameVariables($game, "{PlayniteDir}\app")
$files = @("$PlayniteInstallDir\ReadyRunGame_linktemp.exe", "$PlayniteInstallDir\ReadyCloseGame_linktemp.exe", "$PlayniteInstallDir\ReadyRunGame_runtime.exe", "$PlayniteInstallDir\ReadyCloseGame_runtime.exe", "$PlayniteInstallDir\UserVar.ps1", "$PlayniteInstallDir\Game_Clean.exe")
$GameInstallDir = $PlayniteApi.ExpandGameVariables($game, "{InstallDir}")

放到游戏F3的脚本里面
游戏执行前
Copy-Item -LiteralPath $files -Destination $GameInstallDir -Verbose
Start-Process "$GameInstallDir\ReadyRunGame_linktemp.exe" -Verb RunAs -Wait

游戏执行后
Copy-Item -LiteralPath $files -Destination $GameInstallDir -Verbose
Start-Process "$GameInstallDir\ReadyCloseGame_linktemp.exe" -Verb RunAs -Wait
Start-Sleep -Seconds 5
Remove-Item -Path "$GameInstallDir\Game_Clean.exe" -Recurse -Force


如果你的Game_Clean是ps1脚本,可用删掉
Start-Sleep -Seconds 5
Remove-Item -Path "$GameInstallDir\Game_Clean.exe" -Recurse -Force
用脚本自删的命令



凯诺斯 发表于 2024-5-11 07:51:47

看起来很专业的脚本惹,看起来节省了大量空间呀{:6_165:}

Burry 发表于 2024-5-11 07:58:11

挺方便的脚本,这个可以给网盘做一下瘦身了。

Hadley0T 发表于 2024-5-11 08:10:41

感谢大佬,大佬技术力太高了,可惜我盘里都是奇奇怪怪的东西惹。

shisanlang 发表于 2024-5-11 08:51:12

看了看楼主之前的帖子,竟然可以有这么多游戏,真的是阅历丰富惹_(:з」∠)_感觉等我以后盘里游戏变多了的话可以用试试,会很好使的感觉~

油漆王 发表于 2024-5-11 09:10:57

好专业的样子,但我刚买了新电脑,暂时用不到嘿嘿~

娱乐法师火布偶 发表于 2024-5-11 09:12:54

流程真的是很复杂了,不过最后效果还不错

山涧轶闻 发表于 2024-5-11 09:22:32

哇哦,确实攒了很多VN资源,也很占空间,这下可以攒更多的资源了{:6_169:}

you9632587 发表于 2024-5-11 09:26:07

我是一个大容量机械盘存东西,一个固态作为系统和游戏盘,游戏需要玩的时候才会解压到游戏盘玩完就删所以都够用,不过VN也不太需要放到固态

koh 发表于 2024-5-11 10:08:16

只看这一段代码比上次能接受度高了很多,可以学习以备使用啦

land动了 发表于 2024-5-11 10:11:52

感谢!以后就有法子了

风扇一直转 发表于 2024-5-11 10:56:51

:L:L:L完全看不懂的程度啊思密达

Mercurly 发表于 2024-5-11 10:59:14

码住,刚换了新电脑暂时还用不上惹{:4_114:}

ccczpoa 发表于 2024-5-11 11:05:14

很有用呢,不过换了硬盘现在空间还够,先收藏了

不是卖萌的基佬 发表于 2024-5-11 11:21:17

看不懂但是不妨碍我收藏起来说不定哪天用上了{:4_108:}

li漠北 发表于 2024-5-11 13:45:02

老师老师,怎样可以最大程度压缩小说漫画视频{:3_54:}

hxl251314 发表于 2024-5-11 14:56:30

哇哦下,相当硬核的教程了,确实游戏有点多,硬盘满了

Sean1777 发表于 2024-5-11 15:12:32

有点想试一下 但素看到这些电脑技术类的东西就有点头疼惹

轮回2L 发表于 2024-5-11 15:22:44

学习一下,感觉以后会用上的说{:6_167:}

JYYYY 发表于 2024-5-11 15:26:54

看着很有用的样子,先mark一下,硬盘不够用的时候来看看
页: [1] 2
查看完整版本: 游戏盘被 VN 爆破后如何科学节约储存空间 硬链接兼用版