Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572@echo off
:::: Some basic tests::
echo ------------ Testing FOR loop ------------echo --- Multiple linesfor %%i in (ABC) do echo %%i
echo --- Lines and spacesfor %%i in (D E F) do echo %%i
echo --- Multiple lines and commasfor %%i in (G,H,I) do echo %%i
echo --- Multiple lines and %%I:: The FOR-variable is case-sensitivefor %%i in (J K L) do echo %%I
echo --- Multiple lines and %%jfor %%i in (M,N,O) do echo %%j
echo --- FOR /F token parsing:: This test requires extensions being enabledsetlocal enableextensions
set TEST_STRING="_ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~ ? @ [ \ ] _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~ ? @ [ \ ]"set "ECHO_STRING=?=%%? @=%%@ A=%%A B=%%B C=%%C D=%%D E=%%E F=%%F G=%%G H=%%H I=%%I J=%%J K=%%K L=%%L M=%%M N=%%N O=%%O P=%%P Q=%%Q R=%%R S=%%S T=%%T U=%%U V=%%V W=%%W X=%%X Y=%%Y Z=%%Z [=%%[ \=%%\ ]=%%] ^^=%%^^ _=%%_ `=%%` a=%%a b=%%b c=%%c d=%%d e=%%e f=%%f g=%%g h=%%h i=%%i j=%%j k=%%k l=%%l m=%%m n=%%n o=%%o p=%%p q=%%q r=%%r s=%%s t=%%t u=%%u v=%%v w=%%w x=%%x y=%%y z=%%z {=%%{ ^|=%%^| }=%%} ^~=%%^~"
echo.
:: Bug 1: Ranges that are not specified in increasing order are ignored.:: Token numbers strictly greater than 31 are just ignored, and if they:: appear in a range, the whole range is ignored.
for /f "tokens=30-32" %%? in (%TEST_STRING%) do echo %ECHO_STRING%echo.for /f "tokens=5-1" %%? in (%TEST_STRING%) do echo %ECHO_STRING%echo.
:: Bug 2: Ranges that partially overlap: too many variables are being allocated,:: while only a subset is actually used. This leads to the extra variables returning:: empty strings.
for /f "tokens=1-31,31,31" %%? in (%TEST_STRING%) do echo %ECHO_STRING%echo.for /f "tokens=1-31,1-31" %%? in (%TEST_STRING%) do echo %ECHO_STRING%echo.for /f "tokens=1-5,3,5,6" %%? in (%TEST_STRING%) do echo %ECHO_STRING%echo.for /f "tokens=1-31,* tokens=1-31 tokens=1-20,*" %%? in (%TEST_STRING%) do echo %ECHO_STRING%echo.
:: For comparison, this works:for /f "tokens=1-5,6" %%? in (%TEST_STRING%) do echo %ECHO_STRING%echo.for /f "tokens=1-5,6-10" %%? in (%TEST_STRING%) do echo %ECHO_STRING%echo.
endlocal
echo ---------- Testing AND operator ----------:: Test for TRUE condition - Should be displayedver | find "Ver" > NUL && echo TRUE AND condition
:: Test for FALSE condition - Should not displayver | find "1234" > NUL && echo FALSE AND condition
echo ---------- Testing OR operator -----------:: Test for TRUE condition - Should not displayver | find "Ver" > NUL || echo TRUE OR condition
:: Test for FALSE condition - Should be displayedver | find "1234" > NUL || echo FALSE OR condition
:::: Testing CMD exit codes and errorlevels.:::: Observations::: - OR operator || converts the LHS error code to ERRORLEVEL only on failure;:: - Pipe operator | converts the last error code to ERRORLEVEL.:::: See https://stackoverflow.com/a/34987886/13530036:: and https://stackoverflow.com/a/34937706/13530036:: for more details.::setlocal enableextensions
echo ---------- Testing CMD exit codes and errorlevels ----------
:: Tests for CMD returned exit code.
echo --- CMD /C Direct EXIT call
call :setError 0cmd /c "exit 42"call :checkErrorLevel 42
call :setError 111cmd /c "exit 42"call :checkErrorLevel 42
echo --- CMD /C Direct EXIT /B call
call :setError 0cmd /c "exit /b 42"call :checkErrorLevel 42
call :setError 111cmd /c "exit /b 42"call :checkErrorLevel 42
:: Non-existing ccommand, or command that only changes:: the returned code (but NOT the ERRORLEVEL) and EXIT.
echo --- CMD /C Non-existing command
:: EXIT alone does not change the ERRORLEVELcall :setError 0cmd /c "nonexisting & exit"call :checkErrorLevel 9009
call :setError 111cmd /c "nonexisting & exit"call :checkErrorLevel 9009
call :setError 0cmd /c "nonexisting & exit /b"call :checkErrorLevel 9009
call :setError 111cmd /c "nonexisting & exit /b"call :checkErrorLevel 9009
echo --- CMD /C RMDIR (no ERRORLEVEL set)
call :setError 0cmd /c "rmdir nonexisting & exit"call :checkErrorLevel 0
call :setError 111cmd /c "rmdir nonexisting & exit"call :checkErrorLevel 0
call :setError 0cmd /c "rmdir nonexisting & exit /b"call :checkErrorLevel 0
call :setError 111cmd /c "rmdir nonexisting & exit /b"call :checkErrorLevel 0
:: Failing command (sets ERRORLEVEL to 1) and EXITecho --- CMD /C DIR (sets ERRORLEVEL) - With failure
:: EXIT alone does not change the ERRORLEVELcall :setError 0cmd /c "dir nonexisting>NUL & exit"call :checkErrorLevel 1
call :setError 111cmd /c "dir nonexisting>NUL & exit"call :checkErrorLevel 1
call :setError 0cmd /c "dir nonexisting>NUL & exit /b"call :checkErrorLevel 1
call :setError 111cmd /c "dir nonexisting>NUL & exit /b"call :checkErrorLevel 1
:: Here EXIT changes the ERRORLEVELcall :setError 0cmd /c "dir nonexisting>NUL & exit 42"call :checkErrorLevel 42
call :setError 111cmd /c "dir nonexisting>NUL & exit 42"call :checkErrorLevel 42
call :setError 0cmd /c "dir nonexisting>NUL & exit /b 42"call :checkErrorLevel 42
call :setError 111cmd /c "dir nonexisting>NUL & exit /b 42"call :checkErrorLevel 42
:: Succeeding command (sets ERRORLEVEL to 0) and EXITecho --- CMD /C DIR (sets ERRORLEVEL) - With success
call :setError 0cmd /c "dir>NUL & exit"call :checkErrorLevel 0
call :setError 111cmd /c "dir>NUL & exit"call :checkErrorLevel 0
call :setError 0cmd /c "dir>NUL & exit 42"call :checkErrorLevel 42
call :setError 111cmd /c "dir>NUL & exit 42"call :checkErrorLevel 42
call :setError 0cmd /c "dir>NUL & exit /b 42"call :checkErrorLevel 42
call :setError 111cmd /c "dir>NUL & exit /b 42"call :checkErrorLevel 42
:: Same sorts of tests, but now from within an external batch file::: Tests for CALL command returned exit code.
:: Use an auxiliary CMD filemkdir foobar && cd foobar
:: Non-existing ccommand, or command that only changes:: the returned code (but NOT the ERRORLEVEL) and EXIT.
echo --- CALL Batch Non-existing command
:: EXIT alone does not change the ERRORLEVELecho nonexisting ^& exit /b> tmp.cmdcall :setError 0call tmp.cmdcall :checkErrorLevel 9009
echo nonexisting ^& exit /b> tmp.cmdcall :setError 111call tmp.cmdcall :checkErrorLevel 9009
:: These tests show that || converts the returned error code:: from RMDIR on failure, and converts it to an ERRORLEVEL:: (first two tests: no ||, thus no ERRORLEVEL set;:: last two tests: ||used and ERRORLEVEL is set).::
echo --- CALL Batch RMDIR (no ERRORLEVEL set)
:: This test shows that if a batch returns error code 0 from CALL,:: then CALL will keep the existing ERRORLEVEL (here, 111)...echo rmdir nonexisting> tmp.cmdecho exit /b>> tmp.cmdcall :setError 0call tmp.cmdcall :checkErrorLevel 0
echo rmdir nonexisting> tmp.cmdecho exit /b>> tmp.cmdcall :setError 111call tmp.cmdcall :checkErrorLevel 111
echo --- CALL Batch RMDIR with ^|^| (sets ERRORLEVEL)
:: ... but if a non-zero error code is returned from CALL,:: then CALL uses it as the new ERRORLEVEL.echo rmdir nonexisting ^|^| rem> tmp.cmdecho exit /b>> tmp.cmdcall :setError 0call tmp.cmdcall :checkErrorLevel 2:: This gives the same effect, since the last command's error code:: is returned and transformed by CALL into an ERRORLEVEL:echo rmdir nonexisting> tmp.cmdcall :setError 0call tmp.cmdcall :checkErrorLevel 2
echo rmdir nonexisting ^|^| rem> tmp.cmdecho exit /b>> tmp.cmdcall :setError 111call tmp.cmdcall :checkErrorLevel 2:: This gives the same effect, since the last command's error code:: is returned and transformed by CALL into an ERRORLEVEL:echo rmdir nonexisting> tmp.cmdcall :setError 111call tmp.cmdcall :checkErrorLevel 2
:: Failing command (sets ERRORLEVEL to 1) and EXITecho --- CALL Batch DIR (sets ERRORLEVEL) - With failure
echo dir nonexisting^>NUL> tmp.cmdcall :setError 0call tmp.cmdcall :checkErrorLevel 1
echo dir nonexisting^>NUL> tmp.cmdcall :setError 111call tmp.cmdcall :checkErrorLevel 1
echo dir nonexisting^>NUL ^& goto :eof> tmp.cmdcall :setError 0call tmp.cmdcall :checkErrorLevel 1
echo dir nonexisting^>NUL ^& goto :eof> tmp.cmdcall :setError 111call tmp.cmdcall :checkErrorLevel 1
echo dir nonexisting^>NUL ^& exit /b> tmp.cmdcall :setError 0call tmp.cmdcall :checkErrorLevel 1
echo dir nonexisting^>NUL ^& exit /b> tmp.cmdcall :setError 111call tmp.cmdcall :checkErrorLevel 1
echo dir nonexisting^>NUL ^& exit /b 42 > tmp.cmdcall :setError 0call tmp.cmdcall :checkErrorLevel 42
echo dir nonexisting^>NUL ^& exit /b 42 > tmp.cmdcall :setError 111call tmp.cmdcall :checkErrorLevel 42
:: Succeeding command (sets ERRORLEVEL to 0) and EXITecho --- CALL Batch DIR (sets ERRORLEVEL) - With success
echo dir^>NUL> tmp.cmdcall :setError 0call tmp.cmdcall :checkErrorLevel 0
echo dir^>NUL> tmp.cmdcall :setError 111call tmp.cmdcall :checkErrorLevel 0
echo dir^>NUL ^& goto :eof> tmp.cmdcall :setError 0call tmp.cmdcall :checkErrorLevel 0
echo dir^>NUL ^& goto :eof> tmp.cmdcall :setError 111call tmp.cmdcall :checkErrorLevel 0
echo dir^>NUL ^& exit /b> tmp.cmdcall :setError 0call tmp.cmdcall :checkErrorLevel 0
echo dir^>NUL ^& exit /b> tmp.cmdcall :setError 111call tmp.cmdcall :checkErrorLevel 0
echo dir^>NUL ^& exit /b 42 > tmp.cmdcall :setError 0call tmp.cmdcall :checkErrorLevel 42
echo dir^>NUL ^& exit /b 42 > tmp.cmdcall :setError 111call tmp.cmdcall :checkErrorLevel 42
:: Cleanupdel tmp.cmdcd .. & rmdir /s/q foobar
:::: ERRORLEVEL tests for special commands.:::: For some commands, the errorlevel is set differently,:: whether or not they are run within a .BAT, a .CMD, or:: directly from the command-line.:::: These commands are::: APPEND/DPATH, ASSOC, FTYPE, PATH, PROMPT, SET.:::: See https://ss64.com/nt/errorlevel.html for more details.::
echo ---------- Testing ERRORLEVEL in .BAT and .CMD ----------
:: Use an auxiliary CMD filemkdir foobar && cd foobar
echo --- In .BAT filecall :outputErrLvlTestToBatch tmp.batcmd /c tmp.batdel tmp.bat
echo --- In .CMD filecall :outputErrLvlTestToBatch tmp.cmdcmd /c tmp.cmddel tmp.cmd
:: Cleanupcd .. & rmdir /s/q foobar
:: Go to the next tests below.goto :continue
:: ERRORLEVEL test helper function:outputErrLvlTestToBatch (filename)
echo @echo off> %1echo setlocal enableextensions>> %1
:: Reset the errorlevelecho call :zeroErrLvl>> %1
:: dpath:: echo %errorlevel%:: dpath xxx:: echo %errorlevel%:: dpath:: echo %errorlevel%
echo assoc^>NUL>> %1echo echo %%errorlevel%%>> %1echo assoc .nonexisting^>NUL>> %1echo echo %%errorlevel%%>> %1echo assoc .nonexisting^=^>NUL>> %1echo echo %%errorlevel%%>> %1
:: ftype:: echo %errorlevel%:: ftype xxx:: echo %errorlevel%:: ftype:: echo %errorlevel%
echo path^>NUL>> %1echo echo %%errorlevel%%>> %1echo path^;^>NUL>> %1echo echo %%errorlevel%%>> %1
echo prompt^>NUL>> %1echo echo %%errorlevel%%>> %1echo prompt ^$p^$g^>NUL>> %1echo echo %%errorlevel%%>> %1echo prompt foobar^>NUL>> %1echo echo %%errorlevel%%>> %1
echo set^>NUL>> %1echo echo %%errorlevel%%>> %1echo set nonexisting^>NUL>> %1echo echo %%errorlevel%%>> %1echo set nonexisting^=^>NUL>> %1echo echo %%errorlevel%%>> %1echo set nonexisting^=trololol^>NUL>> %1echo echo %%errorlevel%%>> %1echo set nonexisting^=^>NUL>> %1echo echo %%errorlevel%%>> %1
echo goto :eof>> %1
:: Zero ERRORLEVELecho :zeroErrLvl>> %1echo exit /B 0 >> %1
goto :eof
:::: Next suite of tests.:::continue
:: Testing different ERRORLEVELs from the SET command.:: See https://ss64.com/nt/set.html for more details.
echo ---------- Testing SET /A ERRORLEVELs ----------
echo --- Successcall :setError 0set /a "total=1+1"call :checkErrorLevel 0echo %errorlevel%echo %total%
echo --- Unbalanced parenthesescall :setError 0set /a "total=(2+1"call :checkErrorLevel 1073750988echo %errorlevel%echo %total%
echo --- Missing operandcall :setError 0set /a "total=5*"call :checkErrorLevel 1073750989echo %errorlevel%echo %total%
echo --- Syntax errorcall :setError 0set /a "total=7$3"call :checkErrorLevel 1073750990echo %errorlevel%echo %total%
echo --- Invalid numbercall :setError 0set /a "total=0xdeadbeeg"call :checkErrorLevel 1073750991echo %errorlevel%echo %total%
echo --- Number larger than 32-bitscall :setError 0set /a "total=999999999999999999999999"call :checkErrorLevel 1073750992echo %errorlevel%echo %total%
echo --- Division by zerocall :setError 0set /a "total=1/0"call :checkErrorLevel 1073750993echo %errorlevel%echo %total%
:::: Finished!::echo --------- Finished --------------goto :EOF
:checkErrorLevelif %errorlevel% neq %1 (echo Unexpected errorlevel %errorlevel%, expected %1) else echo OKgoto :eof
:: Subroutine to set errorlevel and return:: in windows nt 4.0, this always sets errorlevel 1, since /b isn't supported:setErrorexit /B %1:: This line runs under cmd in windows NT 4, but not in more modern versions.