1

certutil-hash.cmd的代码:

@echo off
certutil -hashfile "%~dpnx0" md5
pause>nul

我想将整个第二行与变量中的哈希值一起保存。CMD-输出:

MD5 hash from C:\Users\ZerTerO\Desktop\certutil-hash.cmd:
9913d66d0b741494962e94ff540a8147
CertUtil: -hashfile command executed successfully.

对我来说,唯一的解决方案是这样的:

@echo off
cls
call:hashfile
set "md5=%md5: =%"
echo.%md5%
pause>nul
exit

:hashfile
for /f "skip=1 tokens=1 delims=" %%a in ('certutil -hashfile "%~dpnx0" md5') do (set "md5=%%a" & goto:eof)

有没有更优雅的解决方案?

我只需要这样做,因为 Windows 7 和 Windows 8 在值之间写入空格:

set "md5=%md5: =%"

提前致谢...

ZerTerO

4

1 回答 1

2

对于使用参数的CertUtil版本, (请参阅我的评论),您可以更好地处理循环,如下所示:HashAlgorithm

Set "md5="
For /F Delims^= %%G In ('CertUtil -HashFile "%~f0" MD5^|FindStr /VRC:"[^a-f 0-9]"')Do Set "md5=%%G"

或者像这样更健壮:

Set "md5="
For /F Delims^= %%G In ('^""%__APPDIR__%certutil.exe" -HashFile "%~f0" MD5^|"%__APPDIR__%findstr.exe" /VRC:"[^a-f 0-9]"^"')Do @Set "md5=%%G"

使用排除任何包含非字母字符的行a, b, c, d, e, 或f; 数字字符0, 1, 2, 3, 4, 5, 6, 7, 8, 或9; 或空格字符,在我看来,比跳过第一行然后在处理完第二行后跳出循环更优雅。

至于你的结果变量,我不确定,在这种情况下,我是否会费心使用set "md5=%md5: =%"专门删除可能的空格,我只是使用 echo.%md5: =%. 但是,如果我要在剩余的脚本中足够频繁地使用结果变量,我会在标记部分中执行该任务:

@Echo Off
SetLocal EnableExtensions
ClS

Set "algo=MD5"

Call :HashFile "%~f0" %algo%

Echo(%hash%

Pause 1> NUL
GoTo :EOF

:HashFile
Set "hash="
For /F Delims^= %%G In ('^""%__APPDIR__%certutil.exe" -HashFile %1 %2 2^> NUL ^
 ^| "%__APPDIR__%findstr.exe" /V /R /C:"[^a-f 0-9]"^"') Do Set "hash=%%G"
If Not "%hash: =%" == "%hash%" Set "hash=%hash: =%"
Exit /B

理想情况下,行5应该是确定操作系统上的如果不是,那一行将显示为Set "algo=". 您还会注意到我已将您的硬编码文件名移出循环,并将其用作Call命令的第一个输入参数。这应该使您的脚本更加模块化,并且 IMO 更优雅。我还认为%hash%在要求将它们替换为空之前检查是否包含空格会更优雅。优雅和效率不一定是一样的

于 2020-07-23T18:33:47.200 回答