如何从 Shortcuts.vdf 文件中提取我添加到 Steam 快捷方式的游戏的名称?

如何从 Shortcuts.vdf 文件中提取我添加到 Steam 快捷方式的游戏的名称?

我正在尝试整理一份 Excel 表,列出我已向 Steam 添加快捷方式的所有游戏。Steam 允许您向非 Steam 游戏添加快捷方式并充当它们的启动器。用户添加的快捷方式链接位于名为 Shortcuts.vdf 的本地数据库中,其中包含与 Steam 拥有的游戏相关的所有信息。我基本上感兴趣的是游戏的名称。

以下是文件中的数据在记事本中的片段:

shortcuts  0 appid °rõÄappname Cemu Exe "T:\Cemu\App+Update+DLC\Cemu.exe" StartDir "T:\Cemu\App+Update+DLC\" icon  ShortcutPath  LaunchOptions  IsHidden     AllowDesktopConfig    AllowOverlay    openvr     Devkit     DevkitGameID  LastPlayTime ZùÏ_ tags 0 favorite 1 All Games  1 appid }yâappname Citra Nightly Exe "C:\Users\phili\AppData\Local\Citra\nightly-mingw\citra-qt.exe" StartDir "C:\Users\phili\AppData\Local\Citra\nightly-mingw\" icon  ShortcutPath  LaunchOptions  IsHidden     AllowDesktopConfig    AllowOverlay    openvr     Devkit     DevkitGameID  LastPlayTime ¿
ã_ tags 0 favorite 1 All Games  2 appid {Sü¸appname RollerCoaster Tycoon 2: Triple Thrill Pack Open Exe "C:\Program Files\OpenRCT2\openrct2.exe" StartDir "C:\Program Files\OpenRCT2\" icon  ShortcutPath  LaunchOptions  IsHidden     AllowDesktopConfig    AllowOverlay    openvr     Devkit     DevkitGameID  LastPlayTime !Ý_ tags 0 steam 1 All Games  3 appid Iì»Âappname Art Of Fighting 2 Exe "R:\Amazon Games\Library\Art of Fighting 2\ArtOfFighting2.exe" StartDir "R:\Amazon Games\Library\Art of Fighting 2\" icon  ShortcutPath  LaunchOptions  IsHidden     AllowDesktopConfig    AllowOverlay    openvr     Devkit     DevkitGameID  LastPlayTime      tags 0 Shortcuts 1 Amazon 2 All Games  4 appid ñappname Origin Exe "C:\Program Files (x86)\Origin\Origin.exe" StartDir "C:\Program Files (x86)\Origin\" icon  ShortcutPath  LaunchOptions  IsHidden     AllowDesktopConfig    AllowOverlay    openvr     Devkit     DevkitGameID  LastPlayTime ÛÊ*] tags 0 steam 1 All Games  5 appid £á@¤appname A Good Snowman Is Hard To Build Exe "R:\Amazon Games\Library\A Good Snowman Is Hard To Build\Snowman.exe" StartDir "R:\Amazon Games\Library\A Good Snowman Is Hard To Build\" icon  ShortcutPath  LaunchOptions  IsHidden     AllowDesktopConfig    AllowOverlay    openvr     Devkit     DevkitGameID  LastPlayTime      tags 0 Shortcuts 1 Amazon 2 All Games  6 appid ¢‡    æappname Adam Wolfe Exe "R:\Amazon Games\Library\Adam Wolfe\AdamWolfe.exe" StartDir "R:\Amazon

我注意到,我添加到 Steam 的游戏名称总是位于appname和这两个单词之间Exe,如下所示:

£á@¤appname A Good Snowman Is Hard To Build Exe

我如何修改/提取该文件中的条目,以便得到一个包含每行一个单元格之间的条目的 ExcelappnameExe

就像这样:

Excel 表中的条目列表

我可能在考虑正则表达式?我没有 Microsoft Office,只有 Libre Office

原始的快捷方式.vdf文件上传+txt转换版本。

答案1

这应该很容易实现,您只需要 PowerShell,不需要 Office Suite。

从路径的语法来看,它们以驱动器号(即 T:)开头,并使用反斜杠(\)分隔目录,我假设您使用的是 Windows。

如果您使用的是 Windows,请使用以下命令打开 PowerShell:

Win+ →R类型PowerShellCtrl++ShiftEnter

然后,一旦您进入 PowerShell,您就可以使用这个正则表达式来获取游戏名称:(appname)(.*?)(Exe)

Steam .vdf 格式是一种专有格式,因此很难正确解析该格式,但您可能可以使用以下格式:GitHub:Steam-GetOnTop,我不使用Steam,也没有用过包裹,所以我不保证它能起作用。

appname但由于该文件是明文编码的,你可以用 notepad.exe 打开它,而你需要的只是和之间的内容Exe,你可以使用暴力破解的方式:

$shortcuts=((Get-Content "C:\Program Files (x86)\Steam\userdata\149576161\config\shortcuts.vdf").ToCharArray() | where{![char]::IsControl("$_")}) -join ""
($shortcuts | Select-String -pattern "(appname)(.*?)(Exe)" -AllMatches).matches.value | %{$_.Substring(7,$_.Length-10)} | sort-object | out-file "$([environment]::getfolderpath('desktop'))\gamename.txt"

解释:

步骤 1:我们获取 Shortcuts.vdf 的内容,将字符串转换为字符数组,过滤掉控制字符,并连接成字符串

第 2 步:我们打印在第一步中获得的内容并将其传递到管道;我们从管道中获取内容并选择所有匹配的字符串(appname)(.*?)(Exe),并使用().matches.value仅获取匹配的字符串,然后我们摆脱appnameExe并将其导出到位于桌面上的名为 gamename.txt 的文件中。

但是,如果您坚持要导出到只有一列的 Excel 表,请使用以下命令:

$shortcuts=((Get-Content "C:\Program Files (x86)\Steam\userdata\149576161\config\shortcuts.vdf").ToCharArray() | where{![char]::IsControl("$_")}) -join ""
($shortcuts | Select-String -pattern "(appname)(.*?)(Exe)" -AllMatches).matches.value | %{$_.Substring(7,$_.Length-10)} | sort-object | %{[PSCustomObject]@{GameName=$_}} | export-csv "$([environment]::getfolderpath('desktop'))\gamename.csv"

该方法与第一种方法几乎相同,但是我们将结果转换为[PSCustomObject]并将最终结果导出到位于路径“C:\Users\USERNAME\Desktop\gamename.csv”的.csv 文件,而不是.txt 文件。


进一步说明:

Microsoft Docs:什么是 PowerShell?

Microsoft Docs:关于变量

Microsoft Docs:关于 Foreach

Microsoft Docs:关于 PSCustomObject 你想要知道的一切

Microsoft Docs:关于数组你想知道的一切

Microsoft Docs:关于数组

Microsoft Docs:获取内容

Microsoft Docs:选择字符串

Microsoft Docs:输出文件

Microsoft Docs:导出-Csv


输出

如你所说它不包含任何个人信息并将文件附加到问题中,我将在下面发布我得到的结果:

Google Drive

我的第一个方法的输出:

游戏名称.txt

在此处输入图片描述

我的第二种方法的输出:

游戏名称.csv

在此处输入图片描述

来自其他答案的 vbs 方法的输出:

steam.txt

在此处输入图片描述


代码效率分析

第一种方法长度为 358 个字符

第二种方法长度为 396 个字符

该 vbs 脚本长度为 541 个字符

第一种方法打高尔夫球:

$s=((gc "C:\Program Files (x86)\Steam\userdata\149576161\config\shortcuts.vdf").ToCharArray() | ?{![char]::IsControl("$_")}) -join ""
($s | sls "(appname)(.*?)(Exe)" -all).matches.value | %{$_.Substring(7,$_.Length-10)} | sort >"$([environment]::getfolderpath('desktop'))\gamename.txt"

286 个字符长

第二种方法打高尔夫球:

$s=((gc "C:\Program Files (x86)\Steam\userdata\149576161\config\shortcuts.vdf").ToCharArray() | ?{![char]::IsControl("$_")}) -join ""
($s | sls "(appname)(.*?)(Exe)" -all).matches.value | %{$_.Substring(7,$_.Length-10)} | sort | %{[PSCustomObject]@{GameName=$_}} | epcsv "$([environment]::getfolderpath('desktop'))\gamename.csv"

329 个字符长

vbs不会对结果进行排序,也不会自动输出到文件。

以下是运行时测试:

PS C:\Users\Estranger> measure-command {$s=((gc "C:\Users\Estranger\Downloads\shortcuts.vdf").ToCharArray() | ?{![char]::IsControl("$_")}) -join ""
>> ($s | sls "(appname)(.*?)(Exe)" -all).matches.value | %{$_.Substring(7,$_.Length-10)} | sort >"$([environment]::getfolderpath('desktop'))\gamename.txt"}

Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 1
Milliseconds      : 86
Ticks             : 10863660
TotalDays         : 1.25736805555556E-05
TotalHours        : 0.000301768333333333
TotalMinutes      : 0.0181061
TotalSeconds      : 1.086366
TotalMilliseconds : 1086.366

PS C:\Users\Estranger> measure-command {$s=((gc "C:\Users\Estranger\Downloads\shortcuts.vdf").ToCharArray() | ?{![char]::IsControl("$_")}) -join ""
>> ($s | sls "(appname)(.*?)(Exe)" -all).matches.value | %{$_.Substring(7,$_.Length-10)} | sort | %{[PSCustomObject]@{GameName=$_}} | epcsv "$([environment]::getfolderpath('desktop'))\gamename.csv"}

Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 1
Milliseconds      : 171
Ticks             : 11716488
TotalDays         : 1.356075E-05
TotalHours        : 0.000325458
TotalMinutes      : 0.01952748
TotalSeconds      : 1.1716488
TotalMilliseconds : 1171.6488

PS C:\Users\Estranger> measure-command {cscript steam.vbs}

Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 1
Milliseconds      : 338
Ticks             : 13380483
TotalDays         : 1.54866701388889E-05
TotalHours        : 0.000371680083333333
TotalMinutes      : 0.022300805
TotalSeconds      : 1.3380483
TotalMilliseconds : 1338.0483

我的第一个方法显然获胜了,这个负面评价是不公平的,原贴作者没有发布关键信息,所以无论我写得多好,我的代码都无法一开始就解决原贴作者的问题。


对于那些对我的答案投反对票的人,我的答案现在已被编辑,并且你的反对票不再被锁定,请根据客观事实谨慎投票,并请取消反对票。

对于原帖作者,客观地说,另一个答案不如我的答案有效。你一开始没有发布正确的信息,所以我只有错误的信息可以使用。无论我有多好,我都不可能解决你的问题,因为“垃圾进,垃圾出”,另一个回答者只是运气好,在我不在的时候你发布正确的信息时碰巧在线,而且你看到脚本不如我的好,请考虑接受我的答案。


更短的代码:

方法 1 打高尔夫

$s=((gc "C:\Program Files (x86)\Steam\userdata\149576161\config\shortcuts.vdf").ToCharArray() | ?{![char]::IsControl("$_")}) -join ""
($s | sls "(?<=appname)(.*?)(?=Exe)" -All).matches.value | sort > "$([environment]::getfolderpath('desktop'))\gamename.txt"

方法 2 打高尔夫球

$s=((gc "C:\Program Files (x86)\Steam\userdata\149576161\config\shortcuts.vdf").ToCharArray() | ?{![char]::IsControl("$_")}) -join ""
($s | sls "(?<=appname)(.*?)(?=Exe)" -All).matches.value | sort | %{[PSCustomObject]@{GameName=$_}} | epcsv "$([environment]::getfolderpath('desktop'))\gamename.csv"

这些新方法使用的正则表达式将仅匹配游戏名称,但与第一个正则表达式相比,使用它会使运行时间增加 0.3 秒。

这是我使用第二种方法 1 打高尔夫球时在控制台中看到的内容: 在此处输入图片描述

我想回答这个问题并帮助原帖者,仅仅是因为我觉得这个问题很有趣,原帖者想要的东西很有趣,我只是编程方面的初学者,我想通过回答别人用程序发布的问题来提高我的技能,仅此而已...

PS我真的想成为一名黑客......

答案2

这是一段非常老套的 vbscript,它本质上将文件分解shortcuts.vdf为单独的行(基于字符nul),然后在调用的行之后输出下一行AppName。我确实尝试过file使用Chr(0)分隔符进行拆分,但它引发了一个错误。

将以下文件另存为steam.vbs

Dim oFile: Set oFile = CreateObject("Scripting.FileSystemObject").GetFile("shortcuts.vdf")
Dim file : file = oFile.OpenAsTextStream().Read(oFile.Size)

Dim content, i, c

For i = 1 To Len(file)
    c = Asc(Mid(file, i, 1))
    If c = 0 Then 
        content = content & VbCrLf
    ElseIf c > 3 Then
        content = content & Chr(c)
    end If
Next

Dim items : items = Split(content, VbCrLf)

For i = 0 To Ubound(items)
    If Instr(LCase(items(i)), "appname") > 0 Then Wscript.Echo items(i+1)
Next

Set oFile = Nothing

将文件复制shortcuts.vcf到与此代码相同的文件夹中,然后从命令行类型:

cscript steam.vbs > output.txt

在任何文本编辑器中打开输出,您将看到已添加的所有游戏快捷方式的列表。

答案3

有一个非官方的vdf python 模块用于解析 Valve 的 vdf 文件。有了它,解析和写出包含所有名称的 csv 非常简单:

import vdf

def print_names(shortcut_file_path):
    with open(shortcut_file_path, "rb") as f:
        shortcuts = vdf.binary_load(f)

    with open('c:/scratch/shortcuts.csv', 'w') as f:
        f.write('Game Name\n')
        for k, v in shortcuts["shortcuts"].items():
            appname = v.get("appname")
            print(appname)
            f.write(appname + '\n')

print_names("C:/Program Files (x86)/Steam/userdata/149576161/config/shortcuts.vdf")

要查看所有可用字段(“appname”除外),请将以下print行替换为import pprint; pprint.pprint(v); break

与其他 Python 模块一样,使用 安装 vdf pip install vdf

相关内容