BATCH - 将特定的命令输出行写为没有临时文件的变量?
BATCH - Write a specific line of command output as a variable without temp files?
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
对于使用 HashAlgorithm
参数的 CertUtil
版本,(请参阅我的评论),您可以更好地处理循环,像这样:
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"
使用 findstr 排除任何包含非字母字符的行 a
、b
、c
、d
、e
,或f
;数字字符 0
、1
、2
、3
、4
、5
、6
、7
, 8
, 或 9
;或 space 字符,在我看来,比跳过第一行然后在处理完第二行后跳出循环更优雅。
至于你的结果变量,我不确定,在这种情况下,我是否会费心使用 set "md5=%md5: =%"
来专门删除可能的 spaces,我只是使用 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
理想情况下应该是确定 OS 上的 certutil 版本是否支持两个参数的例程的一部分。如果不是,则该行将显示为 Set "algo="
。您还会注意到我已将您的硬编码文件名移出循环,并将其用作 Call
命令的第一个输入参数。这应该使您的脚本更加模块化,并且 IMO 优雅。我还认为在要求将它们替换为空之前检查 %hash%
是否包含 space 更优雅。 优雅与高效未必相同.
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
对于使用 HashAlgorithm
参数的 CertUtil
版本,(请参阅我的评论),您可以更好地处理循环,像这样:
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"
使用 findstr 排除任何包含非字母字符的行 a
、b
、c
、d
、e
,或f
;数字字符 0
、1
、2
、3
、4
、5
、6
、7
, 8
, 或 9
;或 space 字符,在我看来,比跳过第一行然后在处理完第二行后跳出循环更优雅。
至于你的结果变量,我不确定,在这种情况下,我是否会费心使用 set "md5=%md5: =%"
来专门删除可能的 spaces,我只是使用 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
理想情况下应该是确定 OS 上的 certutil 版本是否支持两个参数的例程的一部分。如果不是,则该行将显示为 Set "algo="
。您还会注意到我已将您的硬编码文件名移出循环,并将其用作 Call
命令的第一个输入参数。这应该使您的脚本更加模块化,并且 IMO 优雅。我还认为在要求将它们替换为空之前检查 %hash%
是否包含 space 更优雅。 优雅与高效未必相同.