正如@drruruu 在这个问题中所问的:
这可能吗without临时文件?
是的,没有临时文件也是可能的。通过在 IN 子句中将 ERRORLEVEL 发送到 STDOUT 并在 LOOP 子句中对其进行解析。也可以通过延迟扩展来完成.
为了方便起见,这里举一个例子。它有点像 FINDSTR 包装器,用于在批处理本身中搜索字符串。它涵盖了所有常见情况,您需要知道出了什么问题、出问题在哪里以及为什么出问题:
- DO()子句(又名循环)出错并获取相应的退出代码
- IN()子句出错并获取相应的退出代码
- FOR 子句直接出错(语法错误、分隔符错误等)
以下脚本使用 FINDSTR 和标志作为参数模拟这些情况:
- 第一个参数是要搜索的字符串。
- 第二个参数是 0/1 标志,用于模拟循环中与 FINDSTR 无关的错误。
- 第三个参数是模拟 FOR 子句本身错误的方法(不是 IN 或 LOOP 上的错误)
- 第四个参数是测试 FINDSTR 的方法,当要搜索的文件不存在时退出 255。遗憾的是,FINDSTR 在文件中找不到字符串时会以 1 退出,而在找不到任何文件时也会以 1 退出。通过第四个参数,我们模拟了 FINDSTR 在以下情况下以 255 退出的情况:它找不到该文件。
@echo off
SETLOCAL ENABLEEXTENSIONS
IF ERRORLEVEL 1 (
ECHO Can't use extensions
EXIT /B 1
)
SETLOCAL ENABLEDELAYEDEXPANSION
IF ERRORLEVEL 1 (
ECHO Can't use delayed expansion
EXIT /B 1
)
REM The string to search
SET "LOCALV_STRING=%1"
REM The file to search. Myself.
SET "LOCALV_THIS=%0"
REM Store the exit code for the LOOP
SET "LOCALV_ERR="
REM Store the exit code for the IN
SET "LOCALV_RET="
REM Flag to stop parsing output for error simulation
SET "LOCALV_END="
REM To get the exit code of the IN clause, we get it through expansion with a second FOR loop using the well known CALL expansion and send it on STDOUT in the form "__<code>"
FOR /F "%~3tokens=*" %%M IN ('FINDSTR "!LOCALV_STRING!" "!LOCALV_THIS%~4!" ^
^& FOR /F %%A IN ^("ERRORLEVEL"^) DO @CALL ECHO __%%%%A%%') DO (
SET "LOCALV_TMP=%%~M"
REM Simulate that something goes wrong with FINDSTR I/O
IF NOT EXIST "!LOCALV_THIS!%~4" (
SET "LOCALV_RET=255"
SET LOCALV_END=1
)
IF "!LOCALV_END!" == "" (
REM SImulate a problem in the loop
IF "%2" == "1" (
(CMD /C EXIT /B 127)
SET LOCALV_END=1
) ELSE (
IF NOT "!LOCALV_TMP:~0,2!" == "__" ECHO Found: !LOCALV_TMP!
)
)
IF "!LOCALV_TMP:~0,2!!LOCALV_RET!" == "__" SET "LOCALV_RET=!LOCALV_TMP:__=!"
)
SET "LOCALV_ERR=!ERRORLEVEL!"
REM LOCALV_ERR get the exit code from the last iteration of the for loop
REM LOCALV_RET get the exit code from the IN command of the for loop
REM Sadly, FINDSTR exit with 1 if it did not find the string, but also with 1 if it could not found the file. To simulate a proper handling of exit code for
REM abnormal hardware/software situation, %2 is used to force a 255 exit code
REM If LOCALV_RET is not defined, this means the FOR...ECHO__.. wasn't executed, therefore there is a pb with the FOR LOOP
IF "!LOCALV_RET!" == "" (
ECHO Something went wrong with FOR...
EXIT /B 1
)
REM If LOCALV_RET is defined, this means the FOR...ECHO__.. was executed and the last loop operation has parsed the FINDSTR exit code, LOCALV_RET get its exit code
REM If LOCALV_RET is defined but LOCALV_ERR is not "0", something went wrong in the loop (I/O error, out of memory, wathever you could think), the problem is not FINDSTR
IF NOT "!LOCALV_ERR!" == "0" (
ECHO Error in the loop while searching "!LOCALV_STRING!" in "!LOCALV_THIS!", exit code !LOCALV_RET!. Loop exit code : !LOCALV_ERR!.
EXIT /B 4
)
REM If LOCALV_RET is "0", FINDSTR got matching strings in the file, if "1", FINDSTR don't find any matching string, if anything else, FINDSTR got a problem like failed I/O.
REM If LOCALV_RET is "0" and LOCALV_ERR is "0", everything is ok.
IF "!LOCALV_RET!" == "0" (
ECHO Success.
EXIT /B 0
)
REM If LOCALV_RET is "1" and LOCALV_ERR is "0", FINDSTR failed to find the string in the file "or" failed to find file, for the latter we simulate that FINDSTR exit with 255 .
IF "!LOCALV_RET!" == "1" (
ECHO FINDSTR failed to find "!LOCALV_STRING!" in "!LOCALV_THIS!", exit code !LOCALV_RET!. Loop exit code : !LOCALV_ERR!.
EXIT /B 2
)
REM If LOCALV_RET isn't "0" nor "1" and LOCALV_ERR is "0", FINDSTR failed to do the job and LOCALV_RET got the exit code.
ECHO FINDSTR: Houst^W OP, we've got a problem here while searching "!LOCALV_STRING!" in "!LOCALV_THIS!", exit code !LOCALV_RET!. Loop exit code : !LOCALV_ERR!.
EXIT /B 3
脚本输出:
- 运行正常,模拟无错误。
PROMPT>.\for.bat FOR 0 "" ""
Found: FOR /F "%~3tokens=*" %%M IN ('FINDSTR "FOR" ""
Found: ^& FOR /F %%A IN ^("ERRORLEVEL"^) DO @CALL ECHO __%%%%A%%') DO (
Found: REM If LOCALV_RET is not defined, this means the FOR...ECHO__.. wasn't executed, therefore there is a pb with the FOR LOOP
Found: ECHO Something went wrong with FOR...
Found: REM If LOCALV_RET is defined, this means the FOR...ECHO__.. was executed and the last loop operation has parsed the FINDSTR exit code, LOCALV_RET get its exit code
Success.
- 运行正常,没有错误模拟,有FINDSTR在文件中找不到的字符串。
PROMPT>.\for.bat ZZZ 0 "" ""
FINDSTR failed to find "ZZZ" in ".\for.bat", exit code 1. Loop exit code : 0.
- 模拟LOOP子句中的错误,与FINDSTR无关。
PROMPT>.\for.bat FOR 1 "" ""
Error in the loop while searching "FOR" in ".\for.bat", exit code 0. Loop exit code : 127.
- 使用未知的“delims token”选项模拟 FOR 子句中的错误。
PROMPT>.\for.bat FOR 0 "delims" ""
delimstokens=*" was unexpected.
Something went wrong with FOR...
- 如果找不到文件,则模拟 FINDSTR 退出 255。
PROMPT>.\for.bat FOR 1 "" "ERR"
FINDSTR : Can't open
FINDSTR: HoustW OP, we've got a problem here while searching "FOR" in ".\for.bat", exit code 255. Loop exit code : 0.