【发布时间】:2020-03-11 17:52:34
【问题描述】:
我正在尝试创建一个 Windows bat 文件以在 Windows 10 上使用 GhostScript 和 ImageMagick 7.0.9 比较两个 PDF 文件。第一步为每个页面创建 PNG 文件,并使用“比较”命令创建 magick.exe(没有单独的compare.exe 在 Windows 上)比较图像。不幸的是,即使图像不匹配,“%errorlevel”仍然为 0。
作为一种解决方法,我尝试使用 magick compare 的输出,它在成功时将“0 (0)”发送到 stderr。但是,在这里我无法将 stderr 捕获到环境变量中,可能是因为某些变量范围问题或缺少其他内容。 magick 输出被定向到临时文件,然后用 set /P 加载。通过在魔术比较之后添加暂停,我可以确认 txt 文件在匹配文件中包含“0 (0)”。 echo %SCRIPTRESULT% 什么也不打印。
set /P SCRIPTRESULT=<result/stdtmp.txt
整个bat文件:
@echo off
@rem we assume the current directory is root folder of the test that is being run
@rem get parameters
setlocal
set JOBNAME=%1
set FILETYPE=%2
set PAGECOUNT=%3
set PAGE=1
set FAILPAGE=1
set SCRIPTRESULT=
@rem create the PNG files for two PDFs in ./result/ and ./result_t/ folders
gswin64 -dSAFER -dBATCH -dNOPAUSE -dQUIET -sDEVICE=png16m -sOutputFile=./result/%JOBNAME%_%FILETYPE%_CURR%%d.png -r200 ./result_t/%JOBNAME%.%FILETYPE%
gswin64 -dSAFER -dBATCH -dNOPAUSE -dQUIET -sDEVICE=png16m -sOutputFile=./result/%JOBNAME%_%FILETYPE%_ORIG%%d.png -r200 ./result/%JOBNAME%.%FILETYPE%
@rem gs produces separate PNG for each PDF or PostScript page and we specify the expected count as parameter to this script
FOR /L %%P IN (1,1,%PAGECOUNT%) do (
set PAGE=%%P
rem echo Page %PAGE% of %PAGECOUNT%
magick compare -metric MAE ./result/%JOBNAME%_%FILETYPE%_CURR%PAGE%.png ./result/%JOBNAME%_%FILETYPE%_ORIG%PAGE%.png ./result/%JOBNAME%_%FILETYPE%_DIFF%PAGE%.png 2> result/stdtmp.txt
rem Errorlevel in Windows ImageMagick is always 0 so we need to observe sderr instead?
echo The errorlevel is %errorlevel%
set /P SCRIPTRESULT=<result/stdtmp.txt
echo Compare returned %SCRIPTRESULT%
del /Q .\result\stdtmp.txt
del /Q ".\result\%JOBNAME%_%FILETYPE%_CURR%PAGE%.png"
del /Q ".\result\%JOBNAME%_%FILETYPE%_ORIG%PAGE%.png"
IF "%SCRIPTRESULT%" == "0 (0)" (
echo Deleting .\result\%JOBNAME%_%FILETYPE%_DIFF%PAGE%.png
del /Q ".\result\%JOBNAME%_%FILETYPE%_DIFF%PAGE%.png"
) ELSE (
echo Failed at page %PAGE%
set /A FAILPAGE=%PAGE%
)
)
echo Outside the loop SCRIPTRESULT=%SCRIPTRESULT%
IF "%SCRIPTRESULT%" == "0 (0)" (
echo Files compare OK >&2
)
IF NOT "%SCRIPTRESULT%" == "0 (0)" (
echo Visual compare failed, see ./result/%JOBNAME%_%FILETYPE%_DIFF%FAILPAGE%.png >&2
)
这个脚本可以运行为
compare.bat filename pdf 1
这假设我们有 .\result\filename.pdf 和 .\result_t\filename.pdf,每个都有 1 页。更复杂的是,此比较脚本旨在通过来自另一个脚本的调用来使用。在那种情况下,我会看到输出:
The errorlevel is 0
Compare returned
Fail at page 1
Outside the loop SCRIPTRESULT=0 (0)
Files compare OK
显然循环外的 SCRIPTRESULT 的值是“0 (0)”,正如预期的那样,但不在 FOR 循环内?添加 setlocal ENABLEDELAYEDEXPANSION 没有任何明显效果。
【问题讨论】:
-
您可以使用此处的第二个答案将 stderr 捕获到变量中:stackoverflow.com/questions/29740883/…
-
您需要延迟变量扩展才能使用代码块内变量的更改值。在 for 循环中,您需要使用
!SCRIPTRESULT!而不是%SCRIPTRESULT%。 -
您还需要
!PAGE!,否则无论页数如何,您都只会比较第 1 页。虽然你可以改用%%P。 -
哦,对了——
%ERRORLEVEL%也是如此。您可以查看!ERRORLEVEL!是否有效,或者只使用内置的if errorlevel 1逻辑。 -
与其读入
stdtmp.txt的内容,不如直接用FINDSTR看看有没有你想要的……