1echo Tests for cmd's builtin commands 2 3@echo on 4echo ------------ Testing 'echo' [ON] ------------ 5echo word 6echo 'singlequotedword' 7echo "doublequotedword" 8@echo at-echoed-word 9echo "/?" 10echo. 11echo . 12echo.word 13echo .word 14echo: 15echo : 16echo:word 17echo :word 18echo/ 19echo / 20echo/word 21echo /word 22echo off now 23echo word@space@ 24echo word@space@@space@ 25 echo word 26echo@tab@word 27echo@tab@word @tab@ 28echo@tab@word@tab@@space@ 29@tab@echo word 30echo @tab@word 31echo @tab@word 32echo@tab@@tab@word 33echo @tab@ on @space@ 34@echo --- @ with chains and brackets 35(echo the @ character chains until&&@echo we leave the current depth||( 36echo hidden 37@echo hidden 38))&&echo and can hide brackets||(@echo command hidden)||@(echo brackets hidden) 39@echo --- 40 41@echo off 42echo off@tab@@space@ 43@echo noecho1 44 @echo noecho2 45@@@@@echo echo3 46echo ------------ Testing 'echo' [OFF] ------------ 47echo word 48echo 'singlequotedword' 49echo "doublequotedword" 50@echo at-echoed-word 51echo "/?" 52echo. 53echo . 54echo.word 55echo .word 56echo: 57echo : 58echo:word 59echo :word 60echo/ 61echo / 62echo/word 63echo /word 64echo on again 65echo word@space@ 66echo word@space@@space@ 67 echo word 68echo@tab@word 69echo@tab@word @tab@ 70echo@tab@word@tab@@space@ 71@tab@echo word 72echo @tab@word 73echo @tab@word 74echo@tab@@tab@word 75 76echo ------------ Testing mixed echo modes ------------ 77echo @echo on> mixedEchoModes.cmd 78echo if 1==1 echo foo>> mixedEchoModes.cmd 79echo if 1==1 @echo bar>> mixedEchoModes.cmd 80echo @echo off>> mixedEchoModes.cmd 81echo if 1==1 echo foo2>> mixedEchoModes.cmd 82echo if 1==1 @echo bar2>> mixedEchoModes.cmd 83type mixedEchoModes.cmd 84cmd /c mixedEchoModes.cmd 85del mixedEchoModes.cmd 86 87echo ------------ Testing parameterization ------------ 88call :TestParm a b c 89call :TestParm "a b c" 90call :TestParm "a b"\c 91call :TestParm a=~`+,.{}!+b 92call :TestParm a;b 93call :TestParm "a;b" 94call :TestParm a^;b 95call :TestParm a[b]{c}(d)e 96call :TestParm a&echo second line 97call :TestParm a b,,,c 98call :TestParm a==b;;c 99call :TestParm a,,, b 100goto :TestRem 101 102:TestParm 103echo '%1', '%2', '%3' 104goto :eof 105 106:TestRem 107echo ------------ Testing rem ------------ 108rem Hello 109rem Hello 110rem Hello || foo 111rem echo lol 112rem echo foo & echo bar 113rem @tab@ Hello 114rem@tab@ Hello 115rem@tab@echo foo & echo bar 116@echo on 117rem Hello 118rem Hello 119rem Hello || foo 120rem echo lol 121rem echo foo & echo bar 122rem @tab@ Hello 123rem@tab@ Hello 124rem@tab@echo foo & echo bar 125@echo off 126 127echo ------------ Testing redirection operators ------------ 128mkdir foobar & cd foobar 129echo --- stdout redirection 130echo foo>foo 131type foo 132echo foo 1> foo 133type foo 134echo foo@tab@1> foo 135type foo 136echo foo 1>@tab@foo 137type foo 138echo foo@tab@1>@tab@foo 139type foo 140echo foo7 7> foo 141type foo 142echo foo9 9> foo 143type foo 144echo foo1> foo 145type foo 146echo foo11> foo 147type foo 148echo foo12> foo 149type foo 150echo foo13>"foo" 151type foo 152echo foo14>."\foo" 153type foo 154echo foo15>."\f"oo 155type foo 156del foo 157echo1>foo 158type foo 159echo --- stdout appending 160echo foo>foo 161echo foo >>foo 162type foo 163del foo 164echo foob >> foo 165type foo 166echo fooc 1>>foo 167type foo 168echo food1>>foo 169type foo 170echo food2>>"foo" 171type foo 172del foo 173echo food21>>foo 174type foo 175del foo 176echo foo> foo 177echo foo7 7>> foo || (echo not supported & del foo) 178if exist foo (type foo) else echo not supported 179echo --- redirections within IF statements 180if 1==1 echo foo1>bar 181type bar & del bar 182echo ----- 183if 1==1 (echo foo2>bar) else echo baz2>bar 184type bar & del bar 185if 1==1 (echo foo3) else echo baz3>bar 186type bar || echo file does not exist, ok 187if 1==1 (echo foo4>bar) else echo baz4>bar 188type bar & del bar 189if 1==0 (echo foo5>bar) else echo baz5>bar 190type bar & del bar 191if 1==0 (echo foo6) else echo baz6 1>bar 192type bar & del bar 193if 1==0 (echo foo7 1>bar) else echo baz7>bar 194type bar & del bar 195if 1==0 (echo foo8 1>bar) else echo baz8>bak 196type bak 197if 1==1 (echo foo>bar & echo baz) 198type bar 199if 1==1 ( 200 echo foo>bar 201 echo baz 202) 203type bar 204(if 1==1 (echo A) else echo B) > C 205type C 206(if 1==0 (echo A) else echo B) > C 207type C 208(if 1==0 (echo A > B) else echo C) 209cd .. & rd /s/q foobar 210 211echo ------------ Testing circumflex escape character ------------ 212rem Using something like "echo foo^" asks for an additional char after a "More?" prompt on the following line; it's not possible to currently test that non-interactively 213echo ^hell^o, world 214echo hell^o, world 215echo hell^^o, world 216echo hell^^^o, world 217echo hello^ 218world 219echo hello^ 220 221world 222echo hello^ 223 224 225echo finished 226mkdir foobar 227echo baz> foobar\baz 228type foobar\baz 229type foobar^\baz 230rd /s/q foobar 231echo foo ^| echo bar 232echo foo ^& echo bar 233call :setError 0 234echo bak ^&& echo baz 2> nul 235echo %ErrorLevel% 236echo foo ^> foo 237echo ^<> foo 238type foo 239del foo 240set WINE_FOO=oof 241echo ff^%WINE_FOO% 242set WINE_FOO=bar ^| baz 243set WINE_FOO 244rem FIXME: echoing %WINE_FOO% gives an error (baz not recognized) but prematurely 245rem exits the script on windows; redirecting stdout and/or stderr doesn't help 246echo %ErrorLevel% 247call :setError 0 248set WINE_FOO=bar ^^^| baz 249set WINE_FOO 250echo %WINE_FOO% 251echo %ErrorLevel% 252set WINE_FOO= 253 254echo ------------ Testing chains ------------ 255rem The chain operators have the following bottom-up precedence: 256rem 'else' precedes nothing and matches the closest unmatched 'if' in the same bracket depth 257rem '&' precedes 'else' 258rem '||' precedes '&' and 'else' 259rem '&&' precedes '||', '&' and 'else' 260rem '|' precedes '&&', '||', '&' and 'else' 261rem 262rem Example: 'if 1==1 if 2==2 if 3==3 a | b && c || d & e else f else g' is interpreted as 263rem 'if 1==1 (if 2==2 (if 3==3 ((((a | b) && c) || d) & e) else f) else g)' 264goto :cfailend 265:cfail 266echo %1 267call :setError 1 268goto :eof 269:cfailend 270echo --- chain success 271echo a1&echo a2 272echo b1&&echo b2 273echo c1||echo c2 274echo --- 275echo d1&echo d2&echo d3 276echo e1&echo e2&&echo e3 277echo f1&echo f2||echo f3 278echo --- 279echo g1&&echo g2&echo g3 280echo h1&&echo h2&&echo h3 281echo i1&&echo i2||echo i3 282echo --- 283echo j1||echo j2&echo j3 284echo --- 285echo k1||echo k2&&echo k3 286echo --- 287echo l1||echo l2||echo l3 288echo --- 289echo --- chain failure 290call :cfail a1&call :cfail a2 291call :cfail b1&&call :cfail b2 292echo --- 293call :cfail c1||call :cfail c2 294call :cfail d1&call :cfail d2&call :cfail d3 295call :cfail e1&call :cfail e2&&call :cfail e3 296echo --- 297call :cfail f1&call :cfail f2||call :cfail f3 298call :cfail g1&&call :cfail g2&call :cfail g3 299echo --- 300call :cfail h1&&call :cfail h2&&call :cfail h3 301echo --- 302call :cfail i1&&call :cfail i2||call :cfail i3 303echo --- 304call :cfail j1||call :cfail j2&call :cfail j3 305call :cfail k1||call :cfail k2&&call :cfail k3 306echo --- 307call :cfail l1||call :cfail l2||call :cfail l3 308echo --- chain brackets 309rem Brackets are like regular commands, they support redirections 310rem and have the same precedence as regular commands. 311echo a1&(echo a2&echo a3) 312echo b1&(echo b2&&echo b3) 313echo c1&(echo c2||echo c3) 314echo --- 315echo d1&&(echo d2&echo d3) 316echo e1&&(echo e2&&echo e3) 317echo f1&&(echo f2||echo f3) 318echo --- 319echo g1||(echo g2&echo g3) 320echo --- 321echo h1||(echo h2&&echo h3) 322echo --- 323echo i1||(echo i2||echo i3) 324echo --- 325call :cfail j1&(call :cfail j2&call :cfail j3) 326call :cfail k1&(call :cfail k2&&call :cfail k3) 327echo --- 328call :cfail l1&(call :cfail l2||call :cfail l3) 329call :cfail m1&&(call :cfail m2&call :cfail m3) 330echo --- 331call :cfail n1&&(call :cfail n2&&call :cfail n3) 332echo --- 333call :cfail o1&&(call :cfail o2||call :cfail o3) 334echo --- 335call :cfail p1||(call :cfail p2&call :cfail p3) 336call :cfail q1||(call :cfail q2&&call :cfail q3) 337echo --- 338call :cfail r1||(call :cfail r2||call :cfail r3) 339echo --- chain pipe 340rem Piped commands run at the same time, so the print order varies. 341rem Additionally, they don't run in the batch script context, as shown by 342rem 'call :existing_label|echo read the error message'. 343(echo a 1>&2|echo a 1>&2) 2>&1 344echo --- 345echo b1|echo b2 346echo c1&&echo c2|echo c3 347echo d1||echo d2|echo d3 348echo --- 349echo e1&echo e2|echo e3 350echo f1|echo f2&&echo f3 351echo g1|echo g2||echo g3 352echo --- 353echo h1|echo h2&echo h3 354echo i1|echo i2|echo i3 355echo --- chain pipe input 356rem The output data of the left side of a pipe can disappear, probably 357rem because it finished too fast and closed the pipe before it could be read, 358rem which means we can get broken results for the tests of this section. 359echo @echo off> tmp.cmd 360echo set IN=X>> tmp.cmd 361echo set /p IN=%%1:>> tmp.cmd 362echo setlocal EnableDelayedExpansion>> tmp.cmd 363echo echo [!IN!,%%1]>> tmp.cmd 364echo endlocal>> tmp.cmd 365echo set IN=>> tmp.cmd 366echo a1|cmd /ctmp.cmd a2 367echo b1|cmd /ctmp.cmd b2|cmd /ctmp.cmd b3 368echo c1|cmd /ctmp.cmd c2|cmd /ctmp.cmd c3|cmd /ctmp.cmd c4 369echo d1|call tmp.cmd d2 370echo e1|call tmp.cmd e2|call tmp.cmd e3 371echo f1|call tmp.cmd f2|call tmp.cmd f3|call tmp.cmd f4 372rem FIXME these 3 tests cause "unexpected end of output" 373rem test : echo g1|tmp.cmd g2 374rem result: g2:[g1,g2] 375rem test : echo h1|tmp.cmd h2|tmp.cmd h3 376rem result: h3:[h2:[h1,h2],h3]@or_broken@h3:[h2:,h3] 377rem test : echo i1|tmp.cmd i2|tmp.cmd i3|tmp.cmd i4 378rem result: i4:[i3:[i2:[i1,i2],i3],i4]@or_broken@i4:[i3:[i2:,i3],i4]@or_broken@i4:[i3:,i4] 379del tmp.cmd 380echo --- chain else 381rem Command arguments are gready and eat up the 'else' unless terminated by 382rem brackets, which means the 'else' can only be recognized when the 383rem 'if true' command chain ends with brackets. 384if 1==1 if 2==2 if 3==3 (echo a1) else (echo a2) else echo a3 385if 1==1 if 2==2 if 3==0 (echo b1) else (echo b2) else echo b3 386echo --- 387if 1==1 if 2==0 if 3==3 (echo c1) else (echo c2) else echo c3 388echo --- 389if 1==1 if 2==0 if 3==0 (echo d1) else (echo d2) else echo d3 390echo --- 391if 1==0 if 2==2 if 3==3 (echo e1) else (echo e2) else echo e3 392echo --- 393if 1==0 if 2==2 if 3==0 (echo f1) else (echo f2) else echo f3 394echo --- 395if 1==0 if 2==0 if 3==3 (echo g1) else (echo g2) else echo g3 396echo --- 397if 1==0 if 2==0 if 3==0 (echo h1) else (echo h2) else echo h3 398echo --- 399echo --- chain else (if true) 400if 1==1 echo a1 else echo a2 401if 1==1 echo b1|echo b2 else echo b3 402if 1==1 echo c1&&echo c2 else echo c3 403if 1==1 echo d1||echo d2 else echo d3 404echo --- 405if 1==1 echo e1&echo e2 else echo e3 406if 1==1 echo f1 else echo f2|echo f3 407if 1==1 echo g1 else echo g2&&echo g3 408if 1==1 echo h1 else echo h2||echo h3 409echo --- 410if 1==1 echo i1 else echo i2&echo i3 411if 1==1 echo j1|(echo j2) else echo j3 412echo --- 413if 1==1 echo k1&&(echo k2) else echo k3 414if 1==1 echo l1||(echo l2) else echo l3 415echo --- 416if 1==1 echo m1&(echo m2) else echo m3 417if 1==1 (echo n1) else echo n2|echo n3 418if 1==1 (echo o1) else echo o2&&echo o3 419if 1==1 (echo p1) else echo p2||echo p3 420if 1==1 (echo q1) else echo q2&echo q3 421echo --- chain else (if false) 422if 1==0 echo a1 else echo a2 423if 1==0 echo b1|echo b2 else echo b3 424if 1==0 echo c1&&echo c2 else echo c3 425if 1==0 echo d1||echo d2 else echo d3 426if 1==0 echo e1&echo e2 else echo e3 427if 1==0 echo f1 else echo f2|echo f3 428if 1==0 echo g1 else echo g2&&echo g3 429if 1==0 echo h1 else echo h2||echo h3 430if 1==0 echo i1 else echo i2&echo i3 431if 1==0 echo j1|(echo j2) else echo j3 432echo --- 433if 1==0 echo k1&&(echo k2) else echo k3 434if 1==0 echo l1||(echo l2) else echo l3 435if 1==0 echo m1&(echo m2) else echo m3 436if 1==0 (echo n1) else echo n2|echo n3 437if 1==0 (echo o1) else echo o2&&echo o3 438if 1==0 (echo p1) else echo p2||echo p3 439echo --- 440if 1==0 (echo q1) else echo q2&echo q3 441echo ------------ Testing 'set' ------------ 442call :setError 0 443rem Remove any WINE_FOO* WINE_BA* environment variables from shell before proceeding 444for /f "delims==" %%i in ('set WINE_ba') do set %%i= 445for /f "delims==" %%i in ('set WINE_foo') do set %%i= 446set WINE_FOOBAR 2> nul > nul 447echo %ErrorLevel% 448set WINE_FOOBAR = baz 449echo %ErrorLevel% 450echo %WINE_FOOBAR%WINE_FOOBAR not defined 451echo %WINE_FOOBAR % 452set WINE_FOOBAR 2> nul 453set WINE_FOOBAR = baz2 454echo %ErrorLevel% 455echo %WINE_fOObAr % 456set WINE_FOOBAR= bar 457echo %ErrorLevel% 458echo %WINE_FOOBAR% 459set WINE_FOO 460set WINE_FOOBAR= 461set WINE_FOOB 462echo %WINE_FOOBAR%WINE_FOOBAR not defined 463set WINE_FOOBAR = 464set WINE_FOOBA 2> nul > nul 465echo %ErrorLevel% 466set WINE_FOO=bar 467echo %WINE_FOO% 468set WINE_FOO=foo 469set WINE_BAR=bar 470echo %WINE_FOO%%WINE_BAR% 471set WINE_BAR= 472set WINE_FOO= 473set WINE_FOO=%WINE_FOO% 474echo %WINE_FOO%WINE_FOO not defined 475set WINE_BAZ%=bazbaz 476set WINE_BA 477echo %WINE_BAZ%% 478set WINE_BAZ%= 479echo set "WINE_FOO=bar" should not include the quotes in the variable value 480set "WINE_FOO=bar" 481echo %WINE_FOO% 482set@tab@WINE_FOO=foo 483echo %WINE_FOO% 484set@tab@WINE_FOO= 485echo '%WINE_FOO%' 486set WINE_FOO=foo@space@ 487echo '%WINE_FOO%' 488set WINE_FOO=foo@tab@ 489echo '%WINE_FOO%' 490rem Space symbol must appear in `var` 491set WINE_FOO=value@space@ 492echo '%WINE_FOO%' 493rem Space symbol must NOT appear in `var` 494set "WINE_FOO=value"@space@ 495echo '%WINE_FOO%' 496rem Mixed examples: 497set WINE_FOO=jim fred 498echo '%WINE_FOO%' 499set WINE_FOO="jim" fred 500echo '%WINE_FOO%' 501set "WINE_FOO=jim fred" 502echo '%WINE_FOO%' 503set "WINE_FOO=jim" fred 504echo '%WINE_FOO%' 505rem Only the final quote ends the string 506set "WINE_FOO=apple"banana"grape"orange 507echo '%WINE_FOO%' 508set WINE_FOO= 509 510echo ------------ Testing variable expansion ------------ 511call :setError 0 512echo ~p0 should be path containing batch file 513echo %~p0 514mkdir dummydir 515cd dummydir 516echo %~p0 517cd .. 518rmdir dummydir 519echo ~dp0 should be directory containing batch file 520echo %~dp0 521mkdir dummydir 522cd dummydir 523echo %~dp0 524cd .. 525rmdir dummydir 526echo CD value %CD% 527echo %% 528echo P% 529echo %P 530echo %WINE_UNKNOWN%S 531echo P%WINE_UNKNOWN% 532echo P%WINE_UNKNOWN%S 533echo %ERRORLEVEL 534echo %ERRORLEVEL% 535echo %ERRORLEVEL%%ERRORLEVEL% 536echo %ERRORLEVEL%ERRORLEVEL% 537echo %ERRORLEVEL%% 538echo %ERRORLEVEL%%% 539echo P%ERRORLEVEL% 540echo %ERRORLEVEL%S 541echo P%ERRORLEVEL%S 542 543echo ------------ Testing variable substrings ------------ 544set WINE_VAR=qwerty 545echo %WINE_VAR:~0,1% 546echo %WINE_VAR:~0,3% 547echo %WINE_VAR:~2,2% 548echo '%WINE_VAR:~-2,3%' 549echo '%WINE_VAR:~-2,1%' 550echo %WINE_VAR:~2,-1% 551echo %WINE_VAR:~2,-3% 552echo '%WINE_VAR:~-2,-4%' 553echo %WINE_VAR:~-3,-2% 554set WINE_VAR= 555 556echo ------------ Testing variable substitution ------------ 557echo --- in FOR variables 558for %%i in ("A B" C) do echo %%i 559rem check works when prefix with @ 560@for %%i in ("A B" C) do echo %%i 561rem quotes removal 562for %%i in ("A B" C) do echo '%%~i' 563rem fully qualified path 564for %%f in ("C D" E) do echo %%~ff 565rem drive letter 566for %%i in ("F G" H) do echo %%~di 567rem path 568for %%d in ("I J" K) do echo %%~pd 569rem filename 570for %%i in ("L M" N) do echo %%~ni 571rem file extension 572for %%i in ("O. P.OOL" Q.TABC hello) do echo '%%~xi' 573rem path with short path names 574for %%I in ("R S" T ABCDEFGHIJK.LMNOP) do echo '%%~sI' 575rem file attribute 576for %%i in ("U V" W) do echo '%%~ai' 577echo foo> foo 578for %%i in (foo) do echo '%%~ai' 579for %%i in (foo) do echo '%%~zi' 580del foo 581rem file date/time 582rem Not fully testable, until we can grep dir's output to get foo's creation time in an envvar... 583for %%i in ("a b" c) do echo '%%~ti' 584rem file size 585rem Similar issues as above 586for %%i in ("a b" c) do echo '%%~zi' 587rem combined options 588for %%i in ("d e" f) do echo %%~dpi 589for %%i in ("g h" i) do echo %%~sdi 590for %%i in ("g h" i) do echo %%~dsi 591for %%i in ("j k" l.eh) do echo '%%~xsi' 592for %%i in ("") do echo '%%~i,%%~fi,%%~di,%%~pi,%%~ni,%%~xi,%%~si,%%~ai,%%~ti,%%~zi' 593 594echo --- in parameters 595for %%i in ("A B" C) do call :echoFun %%i 596rem quotes removal 597for %%i in ("A B" C) do call :echoFunQ %%i 598rem fully qualified path 599for %%f in ("C D" E) do call :echoFunF %%f 600rem drive letter 601for %%i in ("F G" H) do call :echoFunD %%i 602rem path 603for %%d in ("I J" K) do call :echoFunP %%d 604rem filename 605for %%i in ("L M" N) do call :echoFunN %%i 606rem file extension 607for %%i in ("O. P.OOL" Q.TABC hello) do call :echoFunX %%i 608rem path with short path names 609for %%I in ("R S" T ABCDEFGHIJK.LMNOP) do call :echoFunS %%I 610rem NT4 aborts whole script execution when encountering ~a, ~t and ~z substitutions, preventing full testing 611rem combined options 612for %%i in ("d e" f) do call :echoFunDP %%i 613for %%i in ("g h" i) do call :echoFunSD %%i 614for %%i in ("g h" i) do call :echoFunDS %%i 615for %%i in ("j k" l.eh) do call :echoFunXS %%i 616 617goto :endEchoFuns 618:echoFun 619echo %1 620goto :eof 621 622:echoFunQ 623echo '%~1' 624goto :eof 625 626:echoFunF 627echo %~f1 628goto :eof 629 630:echoFunD 631echo %~d1 632goto :eof 633 634:echoFunP 635echo %~p1 636goto :eof 637 638:echoFunN 639echo %~n1 640goto :eof 641 642:echoFunX 643echo '%~x1' 644goto :eof 645 646:echoFunS 647rem some NT4 workaround 648set WINE_VAR='%~s1' 649echo %WINE_VAR% 650set WINE_VAR= 651goto :eof 652 653:echoFunDP 654echo %~dp1 655goto :eof 656 657:echoFunSD 658echo %~sd1 659goto :eof 660 661:echoFunDS 662echo %~ds1 663goto :eof 664 665:echoFunXS 666echo '%~xs1' 667goto :eof 668:endEchoFuns 669 670echo ------------ Testing variable delayed expansion ------------ 671rem NT4 doesn't support this 672echo --- default mode (load-time expansion) 673set WINE_FOO=foo 674echo %WINE_FOO% 675echo !WINE_FOO! 676if %WINE_FOO% == foo ( 677 set WINE_FOO=bar 678 if %WINE_FOO% == bar (echo bar) else echo foo 679) 680 681set WINE_FOO=foo 682if %WINE_FOO% == foo ( 683 set WINE_FOO=bar 684 if !WINE_FOO! == bar (echo bar) else echo foo 685) 686 687echo --- runtime (delayed) expansion mode 688setlocal EnableDelayedExpansion 689set WINE_FOO=foo 690echo %WINE_FOO% 691echo !WINE_FOO! 692if %WINE_FOO% == foo ( 693 set WINE_FOO=bar 694 if %WINE_FOO% == bar (echo bar) else echo foo 695) 696 697set WINE_FOO=foo 698if %WINE_FOO% == foo ( 699 set WINE_FOO=bar 700 if !WINE_FOO! == bar (echo bar) else echo foo 701) 702echo %ErrorLevel% 703setlocal DisableDelayedExpansion 704echo %ErrorLevel% 705set WINE_FOO=foo 706echo %WINE_FOO% 707echo !WINE_FOO! 708set WINE_FOO= 709echo --- using /V cmd flag 710echo @echo off> tmp.cmd 711echo set WINE_FOO=foo>> tmp.cmd 712echo echo %%WINE_FOO%%>> tmp.cmd 713echo echo !WINE_FOO!>> tmp.cmd 714echo set WINE_FOO=>> tmp.cmd 715cmd /V:ON /C tmp.cmd 716cmd /V:OfF /C tmp.cmd 717del tmp.cmd 718 719echo ------------ Testing conditional execution ------------ 720echo --- unconditional ampersand 721call :setError 123 & echo foo1 722echo bar2 & echo foo2 723mkdir foobar & cd foobar 724echo > foobazbar 725cd .. & rd /s/q foobar 726if exist foobazbar ( 727 echo foobar not deleted! 728 cd .. 729 rd /s/q foobar 730) else echo foobar deleted 731echo --- on success conditional and 732call :setError 456 && echo foo3 > foo3 733if exist foo3 ( 734 echo foo3 created 735 del foo3 736) else echo foo3 not created 737echo bar4 && echo foo4 738echo --- on failure conditional or 739call :setError 789 || echo foo5 740echo foo6 || echo bar6 > bar6 741if exist bar6 ( 742 echo bar6 created 743 del bar6 744) 745 746echo ------------ Testing cd ------------ 747mkdir foobar 748cd foobar 749echo blabla > singleFile 750dir /b 751echo Current dir: %CD% 752cd 753cd .. 754cd 755cd foobar@space@ 756cd 757cd .. 758cd 759cd @space@foobar 760cd 761cd.. 762cd 763cd foobar 764cd..@space@ 765cd 766if not exist foobar (cd ..) 767cd foobar 768cd@tab@..@tab@@space@@tab@ 769cd 770if not exist foobar (cd ..) 771cd foobar 772mkdir "bar bak" 773cd "bar bak" 774cd 775cd .. 776cd ".\bar bak" 777cd 778cd .. 779cd .\"bar bak" 780cd 781cd .. 782cd bar bak 783cd 784cd "bar bak@space@"@tab@@space@ 785cd 786cd ..\.. 787cd 788rd /Q/s foobar 789mkdir foobar 790cd /d@tab@foobar 791cd 792cd .. 793rd /q/s foobar 794 795echo ------------ Testing type ------------ 796echo bar> foobaz 797@echo on 798type foobaz 799echo --- 800@echo off 801type foobaz@tab@ 802echo ---1 803type ."\foobaz" 804echo ---2 805type ".\foobaz" 806echo ---3 807del foobaz 808 809echo ------------ Testing NUL ------------ 810md foobar & cd foobar 811rem NUL file (non) creation + case insensitivity 812rem Note: "if exist" does not work with NUL, so to check for file existence we use a kludgy workaround 813echo > bar 814echo foo > NUL 815dir /b /a-d 816echo foo > nul 817dir /b /a-d 818echo foo > NuL 819@tab@dir /b@tab@/a-d 820del bar 821rem NUL not special everywhere 822call :setError 123 823echo NUL> foo 824if not exist foo (echo foo should have been created) else ( 825 type foo 826 del foo 827) 828rem Empty file creation 829copy nul foo > nul 830if exist foo ( 831 echo foo created 832 del foo 833 type foo 834) else ( 835 echo *** 836) 837echo 1234 >a.a 838copy a.a+NUL b.b >nul 839call :CheckFileSize a.a 7 b.b 8 840copy NUL+a.a b.b >nul 841call :CheckFileSize a.a 7 b.b 8 842mkdir subdir 843copy a.a+NUL subdir\ >nul 844call :CheckFileSize a.a 7 subdir\a.a 8 845del subdir\a.a 846cd subdir 847copy ..\a.a NUL >nul 848if exist a.a echo Failed 849cd .. 850rd subdir /s /q 851del a.a b.b 852cd .. & rd foobar /s /q 853 854echo ------------ Testing if/else ------------ 855echo --- if/else should work with blocks 856if 0 == 0 ( 857 echo if seems to work 858) else ( 859 echo if seems to be broken 860) 861if 1 == 0 ( 862 echo else seems to be broken 863) else ( 864 echo else seems to work 865) 866if /c==/c ( 867 echo if seems not to detect /c as parameter 868) else ( 869 echo parameter detection seems to be broken 870) 871SET elseIF=0 872if 1 == 1 ( 873 SET /a elseIF=%elseIF%+1 874) else if 1 == 1 ( 875 SET /a elseIF=%elseIF%+2 876) else ( 877 SET /a elseIF=%elseIF%+2 878) 879if %elseIF% == 1 ( 880 echo else if seems to work 881) else ( 882 echo else if seems to be broken 883) 884SET elseIF=0 885if 1 == 2 ( 886 SET /a elseIF=%elseIF%+2 887) else if 1 == 1 ( 888 SET /a elseIF=%elseIF%+1 889) else ( 890 SET /a elseIF=%elseIF%+2 891) 892if %elseIF% == 1 ( 893 echo else if seems to work 894) else ( 895 echo else if seems to be broken 896) 897SET elseIF=0 898if 1 == 2 ( 899 SET /a elseIF=%elseIF%+2 900) else if 1 == 2 ( 901 SET /a elseIF=%elseIF%+2 902) else ( 903 SET /a elseIF=%elseIF%+1 904) 905if %elseIF% == 1 ( 906 echo else if seems to work 907) else ( 908 echo else if seems to be broken 909) 910echo --- case sensitivity with and without /i option 911if bar==BAR echo if does not default to case sensitivity 912if not bar==BAR echo if seems to default to case sensitivity 913if /i foo==FOO echo if /i seems to work 914if /i not foo==FOO echo if /i seems to be broken 915if /I foo==FOO echo if /I seems to work 916if /I not foo==FOO echo if /I seems to be broken 917 918echo --- string comparisons 919if abc == abc (echo equal) else echo non equal 920if abc =="abc" (echo equal) else echo non equal 921if "abc"== abc (echo equal) else echo non equal 922if "abc"== "abc" (echo equal) else echo non equal 923 924echo --- tabs handling 925if@tab@1==1 echo doom 926if @tab@1==1 echo doom 927if 1==1 (echo doom) else@tab@echo quake 928if@tab@not @tab@1==@tab@0 @tab@echo lol 929if 1==0@tab@(echo doom) else echo quake 930if 1==0 (echo doom)@tab@else echo quake 931if 1==0 (echo doom) else@tab@echo quake 932 933echo --- comparison operators 934rem NT4 misevaluates conditionals in for loops so we have to use subroutines as workarounds 935echo ------ for strings 936rem NT4 stops processing of the whole batch file as soon as it finds a 937rem comparison operator non fully uppercased, such as lss instead of LSS, so we 938rem can't test those here. 939if LSS LSS LSSfoo (echo LSS string can be used as operand for LSS comparison) 940if LSS LSS LSS (echo bar) 941if 1.1 LSS 1.10 (echo floats are handled as strings) 942if "9" LSS "10" (echo numbers in quotes recognized!) else echo numbers in quotes are handled as strings 943if not "-1" LSS "1" (echo negative numbers as well) else echo NT4 944if /i foo LSS FoOc echo if /i seems to work for LSS 945if /I not foo LSS FOOb echo if /I seems to be broken for LSS 946set WINE_STR_PARMS=A B AB BA AA 947for %%i in (%WINE_STR_PARMS%) do ( 948 for %%j in (%WINE_STR_PARMS%) do ( 949 call :LSStest %%i %%j)) 950if b LSS B (echo b LSS B) else echo NT4 951if /I b LSS B echo b LSS B insensitive 952if b LSS A echo b LSS A 953if /I b LSS A echo b LSS A insensitive 954if a LSS B (echo a LSS B) else echo NT4 955if /I a LSS B echo a LSS B insensitive 956if A LSS b echo A LSS b 957if /I A LSS b echo A LSS b insensitive 958for %%i in (%WINE_STR_PARMS%) do ( 959 for %%j in (%WINE_STR_PARMS%) do ( 960 call :LEQtest %%i %%j)) 961if b LEQ B (echo b LEQ B) else echo NT4 962if /I b LEQ B echo b LEQ B insensitive 963if b LEQ A echo b LEQ A 964if /I b LEQ A echo b LEQ A insensitive 965if a LEQ B (echo a LEQ B) else echo NT4 966if /I a LEQ B echo a LEQ B insensitive 967if A LEQ b echo A LEQ b 968if /I A LEQ b echo A LEQ b insensitive 969for %%i in (%WINE_STR_PARMS%) do ( 970 for %%j in (%WINE_STR_PARMS%) do ( 971 call :EQUtest %%i %%j)) 972if /I A EQU a echo A EQU a insensitive 973for %%i in (%WINE_STR_PARMS%) do ( 974 for %%j in (%WINE_STR_PARMS%) do ( 975 call :NEQtest %%i %%j)) 976for %%i in (%WINE_STR_PARMS%) do ( 977 for %%j in (%WINE_STR_PARMS%) do ( 978 call :GEQtest %%i %%j)) 979for %%i in (%WINE_STR_PARMS%) do ( 980 for %%j in (%WINE_STR_PARMS%) do ( 981 call :GTRtest %%i %%j)) 982echo ------ for numbers 983if -1 LSS 1 (echo negative numbers handled) 984if not -1 LSS -10 (echo negative numbers handled) 985if not 9 LSS 010 (echo octal handled) 986if not -010 LSS -8 (echo also in negative form) 987if 4 LSS 0x5 (echo hexa handled) 988if not -1 LSS -0x1A (echo also in negative form) 989if 11 LSS 101 (echo 11 LSS 101) 990set WINE_INT_PARMS=0 1 10 9 991for %%i in (%WINE_INT_PARMS%) do ( 992 for %%j in (%WINE_INT_PARMS%) do ( 993 call :LSStest %%i %%j)) 994for %%i in (%WINE_INT_PARMS%) do ( 995 for %%j in (%WINE_INT_PARMS%) do ( 996 call :LEQtest %%i %%j)) 997for %%i in (%WINE_INT_PARMS%) do ( 998 for %%j in (%WINE_INT_PARMS%) do ( 999 call :EQUtest %%i %%j)) 1000if 011 EQU 9 (echo octal ok) 1001if 0xA1 EQU 161 (echo hexa ok) 1002if 0xA1 EQU "161" (echo hexa should be recognized) else (echo string/hexa compare ok) 1003if "0xA1" EQU 161 (echo hexa should be recognized) else (echo string/hexa compare ok) 1004for %%i in (%WINE_INT_PARMS%) do ( 1005 for %%j in (%WINE_INT_PARMS%) do ( 1006 call :NEQtest %%i %%j)) 1007for %%i in (%WINE_INT_PARMS%) do ( 1008 for %%j in (%WINE_INT_PARMS%) do ( 1009 call :GEQtest %%i %%j)) 1010for %%i in (%WINE_INT_PARMS%) do ( 1011 for %%j in (%WINE_INT_PARMS%) do ( 1012 call :GTRtest %%i %%j)) 1013echo ------ for numbers and stringified numbers 1014if not "1" EQU 1 (echo strings and integers not equal) else echo foo 1015if not 1 EQU "1" (echo strings and integers not equal) else echo foo 1016if '1' EQU 1 echo '1' EQU 1 1017if 1 EQU '1' echo 1 EQU '1' 1018if not "1" GEQ 1 (echo foo) else echo bar 1019if "10" GEQ "1" echo "10" GEQ "1" 1020if '1' GEQ 1 (echo '1' GEQ 1) else echo NT4 1021if 1 GEQ "1" echo 1 GEQ "1" 1022if "1" GEQ "1" echo "1" GEQ "1" 1023if '1' GEQ "1" echo '1' GEQ "1" 1024if "10" GEQ "1" echo "10" GEQ "1" 1025if not 1 GEQ '1' (echo non NT4) else echo 1 GEQ '1' 1026for %%i in ("1" '1') do call :GEQtest %%i '1' 1027if "10" GEQ '1' (echo "10" GEQ '1') else echo foo 1028if 1 GEQ "10" (echo 1 GEQ "10") else echo foo 1029if "1" GEQ "10" (echo 1 GEQ "10") else echo foo 1030if '1' GEQ "10" (echo '1' GEQ "10") else echo foo 1031if "10" GEQ "10" (echo "10" GEQ "10") 1032echo --- unconditional ampersand after if one line 1033if "0"=="0" echo 1 & echo 2 & echo 3 else echo 4 1034echo --- 1035echo x & if "0"=="1" echo 1 & echo 2 1036echo --- 1037echo x & if "0"=="1" echo 1 & echo 2 & echo 3 1038echo --- 1039echo x & if "0"=="1" (echo 1 & echo 2 & echo 3) 1040echo --- 1041echo x & if "0"=="1" echo 1 & echo 2 & echo 3 else echo 4 1042echo --- 1043goto :endIfCompOpsSubroutines 1044 1045rem IF subroutines helpers 1046:LSStest 1047if %1 LSS %2 echo %1 LSS %2 1048goto :eof 1049:LEQtest 1050if %1 LEQ %2 echo %1 LEQ %2 1051goto :eof 1052:EQUtest 1053if %1 EQU %2 echo %1 EQU %2 1054goto :eof 1055:NEQtest 1056if %1 NEQ %2 echo %1 NEQ %2 1057goto :eof 1058:GEQtest 1059if %1 GEQ %2 echo %1 GEQ %2 1060goto :eof 1061:GTRtest 1062if %1 GTR %2 echo %1 GTR %2 1063goto :eof 1064 1065:endIfCompOpsSubroutines 1066set WINE_STR_PARMS= 1067set WINE_INT_PARMS= 1068 1069echo ------------ Testing for ------------ 1070echo --- plain FOR 1071for %%i in (A B C) do echo %%i 1072for %%i in (A B C) do echo %%I 1073for %%i in (A B C) do echo %%j 1074for %%i in (A B C) do call :forTestFun1 %%i 1075for %%i in (1,4,1) do echo %%i 1076for %%i in (A, B,C) do echo %%i 1077for %%i in (X) do echo %%i 1078for@tab@%%i in (X2) do echo %%i 1079for %%i in@tab@(X3) do echo %%i 1080for %%i in (@tab@ foo@tab@) do echo %%i 1081for@tab@ %%i in@tab@(@tab@M) do echo %%i 1082for %%i@tab@in (X)@tab@do@tab@echo %%i 1083for@tab@ %%j in@tab@(@tab@M, N, O@tab@) do echo %%j 1084for %%i in (`echo A B`) do echo %%i 1085for %%i in ('echo A B') do echo %%i 1086for %%i in ("echo A B") do echo %%i 1087for %%i in ("A B" C) do echo %%i 1088goto :endForTestFun1 1089:forTestFun1 1090echo %1 1091goto :eof 1092:endForTestFun1 1093echo --- imbricated FORs 1094for %%i in (X) do ( 1095 for %%j in (Y) do ( 1096 echo %%i %%j)) 1097for %%i in (X) do ( 1098 for %%I in (Y) do ( 1099 echo %%i %%I)) 1100for %%i in (A B) do ( 1101 for %%j in (C D) do ( 1102 echo %%i %%j)) 1103for %%i in (A B) do ( 1104 for %%j in (C D) do ( 1105 call :forTestFun2 %%i %%j )) 1106goto :endForTestFun2 1107:forTestFun2 1108echo %1 %2 1109goto :eof 1110:endForTestFun2 1111mkdir foobar & cd foobar 1112mkdir foo 1113mkdir bar 1114mkdir baz 1115echo > bazbaz 1116echo --- basic wildcards 1117for %%i in (ba*) do echo %%i 1118echo --- for /d 1119for /d %%i in (baz foo bar) do echo %%i 2>&1 1120rem Confirm we don't match files: 1121for /d %%i in (bazb*) do echo %%i 2>&1 1122for /d %%i in (bazb2*) do echo %%i 2>&1 1123rem Show we pass through non wildcards 1124for /d %%i in (PASSED) do echo %%i 1125for /d %%i in (xxx) do ( 1126 echo %%i - Should be xxx 1127 echo Expected second line 1128) 1129rem Show we issue no messages on failures 1130for /d %%i in (FAILED?) do echo %%i 2>&1 1131for /d %%i in (FAILED?) do ( 1132 echo %%i - Unexpected! 1133 echo FAILED Unexpected second line 1134) 1135for /d %%i in (FAILED*) do echo %%i 2>&1 1136for /d %%i in (FAILED*) do ( 1137 echo %%i - Unexpected! 1138 echo FAILED Unexpected second line 1139) 1140rem FIXME can't test wildcard expansion here since it's listed in directory 1141rem order, and not in alphabetic order. 1142rem Proper testing would need a currently missing "sort" program implementation. 1143rem for /d %%i in (ba*) do echo %%i>> tmp 1144rem sort < tmp 1145rem del tmp 1146rem for /d %%i in (?a*) do echo %%i>> tmp 1147rem sort < tmp 1148rem del tmp 1149rem for /d %%i in (*) do echo %%i>> tmp 1150rem sort < tmp 1151rem del tmp 1152echo > baz\bazbaz 1153goto :TestForR 1154 1155:SetExpected 1156del temp.bat 2>nul 1157call :WriteLine set WINE_found=N 1158for /l %%i in (1,1,%WINE_expectedresults%) do ( 1159 call :WriteLine if "%%%%WINE_expectedresults.%%i%%%%"=="%%%%~1" set WINE_found=Y 1160 call :WriteLine if "%%%%WINE_found%%%%"=="Y" set WINE_expectedresults.%%i= 1161 call :WriteLine if "%%%%WINE_found%%%%"=="Y" goto :eof 1162) 1163call :WriteLine echo Got unexpected result: "%%%%~1" 1164goto :eof 1165 1166:WriteLine 1167echo %*>> temp.bat 1168goto :EOF 1169 1170:ValidateExpected 1171del temp.bat 2>nul 1172for /l %%i in (1,1,%WINE_expectedresults%) do ( 1173 call :WriteLine if not "%%%%WINE_expectedresults.%%i%%%%"=="" echo Found missing result: "%%%%WINE_expectedresults.%%i%%%%" 1174) 1175call temp.bat 1176del temp.bat 2>nul 1177goto :eof 1178 1179:TestForR 1180rem %CD% does not work on NT4 so use the following workaround 1181for /d %%i in (.) do set WINE_CURDIR=%%~dpnxi 1182 1183echo --- for /R 1184echo Plain directory enumeration 1185set WINE_expectedresults=4 1186set WINE_expectedresults.1=%WINE_CURDIR%\. 1187set WINE_expectedresults.2=%WINE_CURDIR%\bar\. 1188set WINE_expectedresults.3=%WINE_CURDIR%\baz\. 1189set WINE_expectedresults.4=%WINE_CURDIR%\foo\. 1190call :SetExpected 1191for /R %%i in (.) do call temp.bat "%%i" 1192call :ValidateExpected 1193 1194echo Plain directory enumeration from provided root 1195set WINE_expectedresults=4 1196set WINE_expectedresults.1=%WINE_CURDIR%\. 1197set WINE_expectedresults.2=%WINE_CURDIR%\bar\. 1198set WINE_expectedresults.3=%WINE_CURDIR%\baz\. 1199set WINE_expectedresults.4=%WINE_CURDIR%\foo\. 1200if "%CD%"=="" goto :SkipBrokenNT4 1201call :SetExpected 1202for /R "%WINE_CURDIR%" %%i in (.) do call temp.bat "%%i" 1203call :ValidateExpected 1204:SkipBrokenNT4 1205 1206echo File enumeration 1207set WINE_expectedresults=2 1208set WINE_expectedresults.1=%WINE_CURDIR%\baz\bazbaz 1209set WINE_expectedresults.2=%WINE_CURDIR%\bazbaz 1210call :SetExpected 1211for /R %%i in (baz*) do call temp.bat "%%i" 1212call :ValidateExpected 1213 1214echo File enumeration from provided root 1215set WINE_expectedresults=2 1216set WINE_expectedresults.1=%WINE_CURDIR%\baz\bazbaz 1217set WINE_expectedresults.2=%WINE_CURDIR%\bazbaz 1218call :SetExpected 1219for /R %%i in (baz*) do call temp.bat "%%i" 1220call :ValidateExpected 1221 1222echo Mixed enumeration 1223set WINE_expectedresults=6 1224set WINE_expectedresults.1=%WINE_CURDIR%\. 1225set WINE_expectedresults.2=%WINE_CURDIR%\bar\. 1226set WINE_expectedresults.3=%WINE_CURDIR%\baz\. 1227set WINE_expectedresults.4=%WINE_CURDIR%\baz\bazbaz 1228set WINE_expectedresults.5=%WINE_CURDIR%\bazbaz 1229set WINE_expectedresults.6=%WINE_CURDIR%\foo\. 1230call :SetExpected 1231for /R %%i in (. baz*) do call temp.bat "%%i" 1232call :ValidateExpected 1233 1234echo Mixed enumeration from provided root 1235set WINE_expectedresults=6 1236set WINE_expectedresults.1=%WINE_CURDIR%\. 1237set WINE_expectedresults.2=%WINE_CURDIR%\bar\. 1238set WINE_expectedresults.3=%WINE_CURDIR%\baz\. 1239set WINE_expectedresults.4=%WINE_CURDIR%\baz\bazbaz 1240set WINE_expectedresults.5=%WINE_CURDIR%\bazbaz 1241set WINE_expectedresults.6=%WINE_CURDIR%\foo\. 1242call :SetExpected 1243for /R %%i in (. baz*) do call temp.bat "%%i" 1244call :ValidateExpected 1245 1246echo With duplicates enumeration 1247set WINE_expectedresults=12 1248set WINE_expectedresults.1=%WINE_CURDIR%\bar\bazbaz 1249set WINE_expectedresults.2=%WINE_CURDIR%\bar\fred 1250set WINE_expectedresults.3=%WINE_CURDIR%\baz\bazbaz 1251set WINE_expectedresults.4=%WINE_CURDIR%\baz\bazbaz 1252set WINE_expectedresults.5=%WINE_CURDIR%\baz\bazbaz 1253set WINE_expectedresults.6=%WINE_CURDIR%\baz\fred 1254set WINE_expectedresults.7=%WINE_CURDIR%\bazbaz 1255set WINE_expectedresults.8=%WINE_CURDIR%\bazbaz 1256set WINE_expectedresults.9=%WINE_CURDIR%\bazbaz 1257set WINE_expectedresults.10=%WINE_CURDIR%\foo\bazbaz 1258set WINE_expectedresults.11=%WINE_CURDIR%\foo\fred 1259set WINE_expectedresults.12=%WINE_CURDIR%\fred 1260call :SetExpected 1261for /R %%i in (baz* bazbaz fred ba*) do call temp.bat "%%i" 1262call :ValidateExpected 1263 1264echo Strip missing wildcards, keep unwildcarded names 1265set WINE_expectedresults=6 1266set WINE_expectedresults.1=%WINE_CURDIR%\bar\jim 1267set WINE_expectedresults.2=%WINE_CURDIR%\baz\bazbaz 1268set WINE_expectedresults.3=%WINE_CURDIR%\baz\jim 1269set WINE_expectedresults.4=%WINE_CURDIR%\bazbaz 1270set WINE_expectedresults.5=%WINE_CURDIR%\foo\jim 1271set WINE_expectedresults.6=%WINE_CURDIR%\jim 1272call :SetExpected 1273for /R %%i in (baz* fred* jim) do call temp.bat "%%i" 1274call :ValidateExpected 1275 1276echo for /R passed 1277echo --- Complex wildcards unix and windows slash 1278cd .. 1279echo Windows slashes, valid path 1280for %%f in (foobar\baz\bazbaz) do echo ASIS: %%f 1281for %%f in (foobar\baz\*) do echo WC : %%f 1282echo Windows slashes, invalid path 1283for %%f in (foobar\jim\bazbaz) do echo ASIS: %%f 1284for %%f in (foobar\jim\*) do echo WC : %%f 1285echo Unix slashes, valid path 1286for %%f in (foobar/baz/bazbaz) do echo ASIS: %%f 1287for %%f in (foobar/baz/*) do echo WC : %%f 1288echo Unix slashes, invalid path 1289for %%f in (foobar/jim/bazbaz) do echo ASIS: %%f 1290for %%f in (foobar/jim/*) do echo WC : %%f 1291echo Done 1292rd /s/Q foobar 1293echo --- for /L 1294rem Some cases loop forever writing 0s, like e.g. (1,0,1), (1,a,3) or (a,b,c); those can't be tested here 1295for /L %%i in (1,2,0) do echo %%i 1296for@tab@/L %%i in (1,2,0) do echo %%i 1297for /L %%i in (1,2,6) do echo %%i 1298for /l %%i in (1 ,2,6) do echo %%i 1299for /L %%i in (a,2,3) do echo %%i 1300for /L %%i in (1,2,-1) do echo %%i 1301for /L %%i in (-4,-1,-1) do echo %%i 1302for /L %%i in (1,-2,-2) do echo %%i 1303for /L %%i in (1,2,a) do echo %%i 1304echo ErrorLevel %ErrorLevel% 1305for /L %%i in (1,a,b) do echo %%i 1306echo ErrorLevel %ErrorLevel% 1307rem Test boundaries 1308for /l %%i in (1,1,4) do echo %%i 1309for /l %%i in (1,2,4) do echo %%i 1310for /l %%i in (4,-1,1) do echo %%i 1311for /l %%i in (4,-2,1) do echo %%i 1312for /l %%i in (1,-1,4) do echo %%i 1313for /l %%i in (4,1,1) do echo %%i 1314for /L %%i in (a,2,b) do echo %%i 1315for /L %%i in (1,1,1) do echo %%i 1316for /L %%i in (1,-2,-1) do echo %%i 1317for /L %%i in (-1,-1,-1) do echo %%i 1318for /L %%i in (1,2, 3) do echo %%i 1319rem Test zero iteration skips the body of the for 1320for /L %%i in (2,2,1) do ( 1321 echo %%i 1322 echo FAILED 1323) 1324echo --- set /a 1325goto :testseta 1326 1327Rem Ideally for /f can be used rather than building a command to execute 1328rem but that does not work on NT4 1329:checkenvvars 1330if "%1"=="" goto :eof 1331call :executecmd set wine_result=%%%1%% 1332if "%wine_result%"=="%2" ( 1333 echo %1 correctly %2 1334) else echo ERROR: %1 incorrectly %wine_result% [%2] 1335set %1= 1336shift 1337shift 1338rem shift 1339goto :checkenvvars 1340:executecmd 1341%* 1342goto :eof 1343 1344:testseta 1345rem No output when using "set expr" syntax, unless in interactive mode 1346rem Need to use "set envvar=expr" to use in a batch script 1347echo ------ individual operations 1348set WINE_foo=0 1349set /a WINE_foo=1 +2 & call :checkenvvars WINE_foo 3 1350set /a WINE_foo=1 +-2 & call :checkenvvars WINE_foo -1 1351set /a WINE_foo=1 --2 & call :checkenvvars WINE_foo 3 1352set /a WINE_foo=2* 3 & call :checkenvvars WINE_foo 6 1353set /a WINE_foo=-2* -5 & call :checkenvvars WINE_foo 10 1354set /a WINE_foo=12/3 & call :checkenvvars WINE_foo 4 1355set /a WINE_foo=13/3 & call :checkenvvars WINE_foo 4 1356set /a WINE_foo=-13/3 & call :checkenvvars WINE_foo -4 1357rem FIXME Divide by zero should return an error, but error messages cannot be tested with current infrastructure 1358set /a WINE_foo=5 %% 5 & call :checkenvvars WINE_foo 0 1359set /a WINE_foo=5 %% 3 & call :checkenvvars WINE_foo 2 1360set /a WINE_foo=5 %% -3 & call :checkenvvars WINE_foo 2 1361set /a WINE_foo=-5 %% -3 & call :checkenvvars WINE_foo -2 1362set /a WINE_foo=1 ^<^< 0 & call :checkenvvars WINE_foo 1 1363set /a WINE_foo=1 ^<^< 2 & call :checkenvvars WINE_foo 4 1364set /a WINE_foo=1 ^<^< -2 & call :checkenvvars WINE_foo 0 1365set /a WINE_foo=-1 ^<^< -2 & call :checkenvvars WINE_foo 0 1366set /a WINE_foo=-1 ^<^< 2 & call :checkenvvars WINE_foo -4 1367set /a WINE_foo=9 ^>^> 0 & call :checkenvvars WINE_foo 9 1368set /a WINE_foo=9 ^>^> 2 & call :checkenvvars WINE_foo 2 1369set /a WINE_foo=9 ^>^> -2 & call :checkenvvars WINE_foo 0 1370set /a WINE_foo=-9 ^>^> -2 & call :checkenvvars WINE_foo -1 1371set /a WINE_foo=-9 ^>^> 2 & call :checkenvvars WINE_foo -3 1372set /a WINE_foo=5 ^& 0 & call :checkenvvars WINE_foo 0 1373set /a WINE_foo=5 ^& 1 & call :checkenvvars WINE_foo 1 1374set /a WINE_foo=5 ^& 3 & call :checkenvvars WINE_foo 1 1375set /a WINE_foo=5 ^& 4 & call :checkenvvars WINE_foo 4 1376set /a WINE_foo=5 ^& 1 & call :checkenvvars WINE_foo 1 1377set /a WINE_foo=5 ^| 0 & call :checkenvvars WINE_foo 5 1378set /a WINE_foo=5 ^| 1 & call :checkenvvars WINE_foo 5 1379set /a WINE_foo=5 ^| 3 & call :checkenvvars WINE_foo 7 1380set /a WINE_foo=5 ^| 4 & call :checkenvvars WINE_foo 5 1381set /a WINE_foo=5 ^| 1 & call :checkenvvars WINE_foo 5 1382set /a WINE_foo=5 ^^ 0 & call :checkenvvars WINE_foo 5 1383set /a WINE_foo=5 ^^ 1 & call :checkenvvars WINE_foo 4 1384set /a WINE_foo=5 ^^ 3 & call :checkenvvars WINE_foo 6 1385set /a WINE_foo=5 ^^ 4 & call :checkenvvars WINE_foo 1 1386set /a WINE_foo=5 ^^ 1 & call :checkenvvars WINE_foo 4 1387echo ------ precedence and grouping 1388set /a WINE_foo=4 + 2*3 & call :checkenvvars WINE_foo 10 1389set /a WINE_foo=(4+2)*3 & call :checkenvvars WINE_foo 18 1390set /a WINE_foo=4 * 3/5 & call :checkenvvars WINE_foo 2 1391set /a WINE_foo=(4 * 3)/5 & call :checkenvvars WINE_foo 2 1392set /a WINE_foo=4 * 5 %% 4 & call :checkenvvars WINE_foo 0 1393set /a WINE_foo=4 * (5 %% 4) & call :checkenvvars WINE_foo 4 1394set /a WINE_foo=3 %% (5 + 8 %% 3 ^^ 2) & call :checkenvvars WINE_foo 3 1395set /a WINE_foo=3 %% (5 + 8 %% 3 ^^ -2) & call :checkenvvars WINE_foo 3 1396echo ------ octal and hexadecimal 1397set /a WINE_foo=0xf + 3 & call :checkenvvars WINE_foo 18 1398set /a WINE_foo=0xF + 3 & call :checkenvvars WINE_foo 18 1399set /a WINE_foo=015 + 2 & call :checkenvvars WINE_foo 15 1400set /a WINE_foo=3, 8+3,0 & call :checkenvvars WINE_foo 3 1401echo ------ variables 1402set /a WINE_foo=WINE_bar=3, WINE_bar+1 & call :checkenvvars WINE_foo 3 WINE_bar 3 1403set /a WINE_foo=WINE_bar=3, WINE_bar+=1 & call :checkenvvars WINE_foo 3 WINE_bar 4 1404set /a WINE_foo=WINE_bar=3, WINE_baz=1, WINE_baz+=WINE_bar, WINE_baz & call :checkenvvars WINE_foo 3 WINE_bar 3 WINE_baz 4 1405set WINE_bar=3 1406set /a WINE_foo=WINE_bar*= WINE_bar & call :checkenvvars WINE_foo 9 WINE_bar 9 1407set /a WINE_foo=WINE_whateverNonExistingVar & call :checkenvvars WINE_foo 0 1408set WINE_bar=4 1409set /a WINE_foo=WINE_whateverNonExistingVar + WINE_bar & call :checkenvvars WINE_foo 4 WINE_bar 4 1410set WINE_bar=4 1411set /a WINE_foo=WINE_bar -= WINE_bar + 7 & call :checkenvvars WINE_foo -7 WINE_bar -7 1412set WINE_bar=-7 1413set /a WINE_foo=WINE_bar /= 3 + 2 & call :checkenvvars WINE_foo -1 WINE_bar -1 1414set /a WINE_foo=WINE_bar=5, WINE_bar %%=2 & call :checkenvvars WINE_foo 5 WINE_bar 1 1415set WINE_bar=1 1416set /a WINE_foo=WINE_bar ^<^<= 2 & call :checkenvvars WINE_foo 4 WINE_bar 4 1417set WINE_bar=4 1418set /a WINE_foo=WINE_bar ^>^>= 2 & call :checkenvvars WINE_foo 1 WINE_bar 1 1419set WINE_bar=1 1420set /a WINE_foo=WINE_bar ^&= 2 & call :checkenvvars WINE_foo 0 WINE_bar 0 1421set /a WINE_foo=WINE_bar=5, WINE_bar ^|= 2 & call :checkenvvars WINE_foo 5 WINE_bar 7 1422set /a WINE_foo=WINE_bar=5, WINE_bar ^^= 2 & call :checkenvvars WINE_foo 5 WINE_bar 7 1423set WINE_baz=4 1424set /a WINE_foo=WINE_bar=19, WINE_bar %%= 4 + (WINE_baz %%= 7) & call :checkenvvars WINE_foo 19 WINE_bar 3 WINE_baz 4 1425echo --- quotes 1426set /a WINE_foo=1 1427call :checkenvvars WINE_foo 1 1428set /a "WINE_foo=1" 1429call :checkenvvars WINE_foo 1 1430set /a WINE_foo=1,WINE_bar=2 1431call :checkenvvars WINE_foo 1 WINE_bar 2 1432set /a "WINE_foo=1,WINE_bar=2" 1433call :checkenvvars WINE_foo 1 WINE_bar 2 1434set /a "WINE_foo=1","WINE_bar=2" 1435call :checkenvvars WINE_foo 1 WINE_bar 2 1436set /a ""WINE_foo=1","WINE_bar=2"" 1437call :checkenvvars WINE_foo 1 WINE_bar 2 1438set /a WINE_foo=1,WINE_bar=2,WINE_baz=3 1439call :checkenvvars WINE_foo 1 WINE_bar 2 WINE_baz 3 1440set /a "WINE_foo=1,WINE_bar=2,WINE_baz=3" 1441call :checkenvvars WINE_foo 1 WINE_bar 2 WINE_baz 3 1442set /a "WINE_foo=1","WINE_bar=2","WINE_baz=3" 1443call :checkenvvars WINE_foo 1 WINE_bar 2 WINE_baz 3 1444set /a ""WINE_foo=1","WINE_bar=2","WINE_baz=3"" 1445call :checkenvvars WINE_foo 1 WINE_bar 2 WINE_baz 3 1446set /a ""WINE_foo=1","WINE_bar=2"","WINE_baz=3" 1447call :checkenvvars WINE_foo 1 WINE_bar 2 WINE_baz 3 1448set /a """"""WINE_foo=1"""""" 1449call :checkenvvars WINE_foo 1 1450set /a """"""WINE_foo=1","WINE_bar=5""","WINE_baz=2"" 1451call :checkenvvars WINE_foo 1 WINE_bar 5 WINE_baz 2 1452set /a WINE_foo="3"+"4"+"5+6" 1453call :checkenvvars WINE_foo 18 1454set WINE_foo=3 1455set /a WINE_bar="WINE_""foo"+4 1456call :checkenvvars WINE_foo 3 WINE_bar 7 1457echo --- whitespace are ignored between double char operators 1458set WINE_foo=4 1459set WINE_bar=5 1460set /a WINE_foo + = 6 1461set /a WINE_bar * = WINE_foo 1462call :checkenvvars WINE_foo 10 WINE_bar 50 1463set WINE_foo=4 1464set WINE_bar=5 1465set /a WINE_foo + = "6 < < 7" 1466set /a WINE_bar * = WINE_foo + WINE_foo 1467call :checkenvvars WINE_foo 772 WINE_bar 7720 1468set /a WINE_foo=6 7 1469set /a WINE_ var1=8 1470set WINE_foo= 1471echo --- invalid operator sequence 1472set WINE_foo=4 1473set /a =4 1474set /a *=4 1475set /a ^>=4" 1476set /a ^<=4" 1477set /a WINE_foo^>^<=4 1478echo %WINE_foo% 1479set /a WINE_foo^>^>^>=4 1480echo %WINE_foo% 1481echo ----- negative prefix 1482set /a WINE_foo=-1 1483call :checkenvvars WINE_foo -1 1484set /a WINE_foo=--1 1485call :checkenvvars WINE_foo 1 1486set /a WINE_foo=3--3 1487call :checkenvvars WINE_foo 6 1488set /a WINE_foo=3---3 1489call :checkenvvars WINE_foo 0 1490set /a WINE_foo=3----3 1491call :checkenvvars WINE_foo 6 1492set /a WINE_foo=-~1 1493call :checkenvvars WINE_foo 2 1494set /a WINE_foo=~-1 1495call :checkenvvars WINE_foo 0 1496set /a WINE_foo=3+-~1 1497call :checkenvvars WINE_foo 5 1498set /a WINE_foo=3+~-1 1499call :checkenvvars WINE_foo 3 1500echo ----- assignment tests involving the end destination 1501set WINE_foo=3 1502set /a WINE_foo+=3+(WINE_foo=4) 1503call :checkenvvars WINE_foo 11 1504set WINE_foo=2 1505set /a WINE_bar=3+(WINE_foo=6) 1506call :checkenvvars WINE_foo 6 WINE_bar 9 1507set WINE_foo=2 1508set /a WINE_bar=3+(WINE_foo=6,WINE_baz=7) 1509call :checkenvvars WINE_foo 6 WINE_bar 10 WINE_baz 7 1510set WINE_foo=2 1511set /a WINE_bar=WINE_foo=7 1512call :checkenvvars WINE_foo 7 WINE_bar 7 1513echo ----- equal precedence on stack 1514rem Unary - don't reduce if precedence is equal 1515set /a WINE_foo=!!1 1516call :checkenvvars WINE_foo 1 1517set /a WINE_foo=!!0 1518call :checkenvvars WINE_foo 0 1519set /a WINE_foo=~~1 1520call :checkenvvars WINE_foo 1 1521set /a WINE_foo=~~0 1522call :checkenvvars WINE_foo 0 1523set /a WINE_foo=--1 1524call :checkenvvars WINE_foo 1 1525set /a WINE_foo=+-1 1526call :checkenvvars WINE_foo -1 1527set /a WINE_foo=-+1 1528call :checkenvvars WINE_foo -1 1529set /a WINE_foo=++1 1530call :checkenvvars WINE_foo 1 1531set /a WINE_foo=!~1 1532call :checkenvvars WINE_foo 0 1533set /a WINE_foo=~!1 1534call :checkenvvars WINE_foo -1 1535set /a WINE_foo=!-1 1536call :checkenvvars WINE_foo 0 1537set /a WINE_foo=-!1 1538call :checkenvvars WINE_foo 0 1539set /a WINE_foo=!-0 1540call :checkenvvars WINE_foo 1 1541set /a WINE_foo=-!0 1542call :checkenvvars WINE_foo -1 1543rem Aritmatic - Reduce if precedence is equal 1544set /a WINE_foo=10*5/2 1545call :checkenvvars WINE_foo 25 1546set /a WINE_foo=5/2*10 1547call :checkenvvars WINE_foo 20 1548set /a WINE_foo=10/5/2 1549call :checkenvvars WINE_foo 1 1550set /a WINE_foo=5%%2*4 1551call :checkenvvars WINE_foo 4 1552set /a WINE_foo=10-5+2 1553call :checkenvvars WINE_foo 7 1554set /a WINE_foo=1^<^<4^>^>1 1555call :checkenvvars WINE_foo 8 1556rem Assignment - don't reduce if precedence is equal 1557set /a WINE_foo=5 1558set /a WINE_bar=WINE_foo=6 1559call :checkenvvars WINE_foo 6 WINE_bar 6 1560 1561echo --- for /F 1562mkdir foobar & cd foobar 1563echo ------ string argument 1564rem NT4 does not support usebackq 1565for /F %%i in ("a b c") do echo %%i 1566for /f usebackq %%i in ('a b c') do echo %%i>output_file 1567if not exist output_file (echo no output) else (type output_file & del output_file) 1568for /f %%i in ("a ") do echo %%i 1569for /f usebackq %%i in ('a ') do echo %%i>output_file 1570if not exist output_file (echo no output) else (type output_file & del output_file) 1571for /f %%i in ("a") do echo %%i 1572for /f usebackq %%i in ('a') do echo %%i>output_file 1573if not exist output_file (echo no output) else (type output_file & del output_file) 1574fOr /f %%i in (" a") do echo %%i 1575for /f usebackq %%i in (' a') do echo %%i>output_file 1576if not exist output_file (echo no output) else (type output_file & del output_file) 1577for /f %%i in (" a ") do echo %%i 1578for /f usebackq %%i in (' a ') do echo %%i>output_file 1579if not exist output_file (echo no output) else (type output_file & del output_file) 1580echo ------ fileset argument 1581echo --------- basic blank handling 1582echo a b c>foo 1583for /f %%i in (foo) do echo %%i 1584echo a >foo 1585for /f %%i in (foo) do echo %%i 1586echo a>foo 1587for /f %%i in (foo) do echo %%i 1588echo a>foo 1589for /f %%i in (foo) do echo %%i 1590echo a >foo 1591for /f %%i in (foo) do echo %%i 1592echo. > foo 1593for /f %%i in (foo) do echo %%i 1594echo. >> foo 1595echo b > foo 1596for /f %%i in (foo) do echo %%i 1597echo --------- multi-line with empty lines 1598echo a Z f> foo 1599echo. >> foo 1600echo.>> foo 1601echo b bC>> foo 1602echo c>> foo 1603echo. >> foo 1604for /f %%b in (foo) do echo %%b 1605echo --------- multiple files 1606echo q w > bar 1607echo.>> bar 1608echo kkk>>bar 1609for /f %%k in (foo bar) do echo %%k 1610for /f %%k in (bar foo) do echo %%k 1611echo ------ command argument 1612rem Not implemented on NT4, need to skip it as no way to get output otherwise 1613if "%CD%"=="" goto :SkipFORFcmdNT4 1614for /f %%i in ('echo.Passed1') do echo %%i 1615for /f "usebackq" %%i in (`echo.Passed2`) do echo %%i 1616for /f usebackq %%i in (`echo.Passed3`) do echo %%i 1617goto :ContinueFORF 1618:SkipFORFcmdNT4 1619for /l %%i in (1,1,3) do echo Missing functionality - Broken%%i 1620:ContinueFORF 1621rem FIXME: Rest not testable right now in wine: not implemented and would need 1622rem preliminary grep-like program implementation (e.g. like findstr or fc) even 1623rem for a simple todo_wine test 1624rem (for /f "usebackq" %%i in (`echo z a b`) do echo %%i) || echo not supported 1625rem (for /f usebackq %%i in (`echo z a b`) do echo %%i) || echo not supported 1626echo ------ eol option 1627if "%CD%"=="" goto :SkipFORFeolNT4 1628echo Line one>foo 1629echo and Line two>>foo 1630echo Line three>>foo 1631for /f "eol=L" %%i in (foo) do echo %%i 1632for /f "eol=a" %%i in (foo) do echo %%i 1633del foo 1634goto :ContinueFORFeol 1635:SkipFORFeolNT4 1636for /l %%i in (1,1,3) do echo Broken NT4 functionality%%i 1637:ContinueFORFeol 1638for /f "eol=@" %%i in (" ad") do echo %%i 1639for /f "eol=@" %%i in (" z@y") do echo %%i 1640for /f "eol=|" %%i in ("a|d") do echo %%i 1641for /f "eol=@" %%i in ("@y") do echo %%i > output_file 1642if not exist output_file (echo no output) else (del output_file) 1643for /f "eol==" %%i in ("=y") do echo %%i > output_file 1644if not exist output_file (echo no output) else (del output_file) 1645echo ------ delims option 1646for /f "delims=|" %%i in ("a|d") do echo %%i 1647for /f "delims=|" %%i in ("a |d") do echo %%i 1648for /f "delims=|" %%i in ("a d|") do echo %%i 1649for /f "delims=| " %%i in ("a d|") do echo %%i 1650for /f "delims==" %%i in ("C r=d|") do echo %%i 1651for /f "delims=" %%i in ("foo bar baz") do echo %%i 1652for /f "delims=" %%i in ("c:\foo bar baz\..") do echo %%~fi 1653echo ------ skip option 1654echo a > foo 1655echo b >> foo 1656echo c >> foo 1657for /f "skip=2" %%i in (foo) do echo %%i 1658for /f "skip=3" %%i in (foo) do echo %%i > output_file 1659if not exist output_file (echo no output) else (del output_file) 1660for /f "skip=4" %%i in (foo) do echo %%i > output_file 1661if not exist output_file (echo no output) else (del output_file) 1662for /f "skip=02" %%i in (foo) do echo %%i 1663for /f "skip=0x2" %%i in (foo) do echo %%i 1664for /f "skip=1" %%i in ("skipme") do echo %%i > output_file 1665if not exist output_file (echo no output) else (del output_file) 1666echo ------ tokens= option 1667rem Basic 1668for /f %%i in ("a b c d e f g") do echo h=%%h i=%%i j=%%j k=%%k l=%%l m=%%m o=%%o 1669for /f "tokens=2" %%i in ("a b c d e f g") do echo h=%%h i=%%i j=%%j k=%%k l=%%l m=%%m o=%%o 1670for /f "tokens=1,3,5-7" %%i in ("a b c d e f g") do echo h=%%h i=%%i j=%%j k=%%k l=%%l m=%%m o=%%o 1671rem Show * means the rest 1672for /f "tokens=1,5*" %%i in ("a b c d e f g") do echo h=%%h i=%%i j=%%j k=%%k l=%%l m=%%m o=%%o 1673for /f "tokens=6,9*" %%i in ("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") do echo h=%%h i=%%i j=%%j k=%%k l=%%l m=%%m o=%%o 1674rem Show * means the rest (not tokenized and rebuilt) 1675for /f "tokens=6,9*" %%i in ("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") do echo h=%%h i=%%i j=%%j k=%%k l=%%l m=%%m o=%%o 1676rem Order is irrelevant 1677for /f "tokens=1,2,3*" %%i in ("a b c d e f g") do echo h=%%h i=%%i j=%%j k=%%k l=%%l m=%%m n=%%n o=%%o 1678for /f "tokens=3,2,1*" %%i in ("a b c d e f g") do echo h=%%h i=%%i j=%%j k=%%k l=%%l m=%%m n=%%n o=%%o 1679rem Duplicates are ignored 1680for /f "tokens=1,2,1*" %%i in ("a b c d e f g") do echo h=%%h i=%%i j=%%j k=%%k l=%%l m=%%m n=%%n o=%%o 1681rem Large tokens are allowed 1682for /f "tokens=25,1,5*" %%i in ("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") do echo h=%%h i=%%i j=%%j k=%%k l=%%l m=%%m n=%%n o=%%o 1683rem Show tokens blanked in advance regardless of uniqueness of requested tokens 1684for /f "tokens=1,1,1,2*" %%i in ("a b c d e f g") do echo h=%%h i=%%i j=%%j k=%%k l=%%l m=%%m n=%%n o=%%o 1685for /f "tokens=1-2,1-2,1-2" %%i in ("a b c d e f g") do echo h=%%h i=%%i j=%%j k=%%k l=%%l m=%%m n=%%n o=%%o 1686rem Show No wrapping from z to A BUT wrapping sort of occurs Z to a occurs 1687for /f "tokens=1-20" %%u in ("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") do echo u=%%u v=%%v w=%%w x=%%x y=%%y z=%%z A=%%A a=%%a 1688for /f "tokens=1-20" %%U in ("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") do echo U=%%U V=%%V W=%%W X=%%X Y=%%Y Z=%%Z A=%%A a=%%a 1689rem Show negative ranges have no effect 1690for /f "tokens=1-3,5" %%i in ("a b c d e f g") do echo h=%%h i=%%i j=%%j k=%%k l=%%l m=%%m o=%%o 1691for /f "tokens=3-1,5" %%i in ("a b c d e f g") do echo h=%%h i=%%i j=%%j k=%%k l=%%l m=%%m o=%%o 1692rem Show duplicates stop * from working 1693for /f "tokens=1,2,3*" %%i in ("a b c d e f g") do echo h=%%h i=%%i j=%%j k=%%k l=%%l m=%%m n=%%n o=%%o 1694for /f "tokens=1,1,3*" %%i in ("a b c d e f g") do echo h=%%h i=%%i j=%%j k=%%k l=%%l m=%%m n=%%n o=%%o 1695for /f "tokens=2,2,3*" %%i in ("a b c d e f g") do echo h=%%h i=%%i j=%%j k=%%k l=%%l m=%%m n=%%n o=%%o 1696for /f "tokens=3,2,3*" %%i in ("a b c d e f g") do echo h=%%h i=%%i j=%%j k=%%k l=%%l m=%%m n=%%n o=%%o 1697cd .. 1698rd /s/q foobar 1699echo ------ parameter splitting 1700echo forFParameterSplittingFunc "myparam1=myvalue1 myparam2=myparam2" mytest> foo 1701for /f "tokens=1 delims=;" %%i in (foo) do (call :%%i) 1702del foo 1703for /f "tokens=1 delims=;" %%i in ("forFParameterSplittingFunc "myparam1^=myvalue1 myparam2^=myparam2" mytest") do (call :%%i) 1704goto :forFParameterSplittingEnd 1705:forFParameterSplittingFunc 1706echo %~0 %~1 %~2 %~3 %~4 %~5 1707goto :eof 1708:forFParameterSplittingEnd 1709 1710echo ------------ Testing del ------------ 1711echo abc > file 1712echo deleting 'file' 1713del file 1714if errorlevel 0 ( 1715 echo errorlevel is 0, good 1716) else ( 1717 echo unexpected errorlevel, got %errorlevel% 1718) 1719if not exist file ( 1720 echo successfully deleted 'file' 1721) else ( 1722 echo error deleting 'file' 1723) 1724echo attempting to delete 'file', even though it is not present 1725del file 1726if errorlevel 0 ( 1727 echo errorlevel is 0, good 1728) else ( 1729 echo unexpected errorlevel, got %errorlevel% 1730) 1731 1732echo ------------ Testing del /a ------------ 1733del /f/q *.test > nul 1734echo r > r.test 1735attrib +r r.test 1736echo not-r > not-r.test 1737 1738if not exist not-r.test echo not-r.test not found before delete, bad 1739del /a:-r *.test 1740if not exist not-r.test echo not-r.test not found after delete, good 1741 1742if not exist r.test echo r.test not found before delete, bad 1743if exist r.test echo r.test found before delete, good 1744del /a:r *.test 1745if not exist r.test echo r.test not found after delete, good 1746if exist r.test echo r.test found after delete, bad 1747 1748echo ------------ Testing del /q ------------ 1749mkdir del_q_dir 1750cd del_q_dir 1751echo abc > file1 1752echo abc > file2.dat 1753rem If /q doesn't work, cmd will prompt and the test case should hang 1754del /q * > nul 1755for %%a in (1 2.dat) do if exist file%%a echo del /q * failed on file%%a 1756for %%a in (1 2.dat) do if not exist file%%a echo del /q * succeeded on file%%a 1757cd .. 1758rmdir del_q_dir 1759 1760echo ------------ Testing del /s ------------ 1761mkdir "foo bar" 1762cd "foo bar" 1763mkdir "foo:" 1764echo hi > file1.dat 1765echo there > file2.dat 1766echo bub > file3.dat 1767echo bye > "file with spaces.dat" 1768cd .. 1769del /s file1.dat > nul 1770del file2.dat /s > nul 1771del "file3.dat" /s > nul 1772del "file with spaces.dat" /s > nul 1773cd "foo bar" 1774for %%f in (1 2 3) do if exist file%%f.dat echo Del /s failed on file%%f 1775for %%f in (1 2 3) do if exist file%%f.dat del file%%f.dat 1776if exist "file with spaces.dat" echo Del /s failed on "file with spaces.dat" 1777if exist "file with spaces.dat" del "file with spaces.dat" 1778rmdir "foo:" 1779cd .. 1780rmdir "foo bar" 1781 1782echo ------------ Testing rename ------------ 1783mkdir foobar & cd foobar 1784echo --- ren and rename are synonymous 1785echo > foo 1786rename foo bar 1787if exist foo echo foo should be renamed! 1788if exist bar echo foo renamed to bar 1789ren bar foo 1790if exist bar echo bar should be renamed! 1791if exist foo echo bar renamed to foo 1792echo --- name collision 1793echo foo>foo 1794echo bar>bar 1795ren foo bar 2> nul 1796type foo 1797type bar 1798rem no-op 1799ren foo foo 1800mkdir baz 1801ren foo baz\abc 1802echo --- rename read-only files 1803echo > file1 1804attrib +r file1 1805ren file1 file2 1806if not exist file1 ( 1807 if exist file2 ( 1808 echo read-only file renamed 1809 ) 1810) else ( 1811 echo read-only file not renamed! 1812) 1813echo --- rename directories 1814mkdir rep1 1815ren rep1 rep2 1816if not exist rep1 ( 1817 if exist rep2 ( 1818 echo dir renamed 1819 ) 1820) 1821attrib +r rep2 1822ren rep2 rep1 1823if not exist rep2 ( 1824 if exist rep1 ( 1825 echo read-only dir renamed 1826 ) 1827) 1828echo --- rename in other directory 1829if not exist baz\abc ( 1830 echo rename impossible in other directory 1831 if exist foo echo original file still present 1832) else ( 1833 echo shouldn't rename in other directory! 1834 if not exist foo echo original file not present anymore 1835) 1836cd .. & rd /s/q foobar 1837 1838echo ------------ Testing move ------------ 1839mkdir foobar & cd foobar 1840echo --- file move 1841echo >foo 1842move foo bar > nul 2>&1 1843if not exist foo ( 1844 if exist bar ( 1845 echo file move succeeded 1846 ) 1847) 1848echo bar>bar 1849echo baz> baz 1850move /Y bar baz > nul 2>&1 1851if not exist bar ( 1852 if exist baz ( 1853 echo file move with overwrite succeeded 1854 ) 1855) else ( 1856 echo file overwrite impossible! 1857 del bar 1858) 1859type baz 1860 1861attrib +r baz 1862move baz bazro > nul 2>&1 1863if not exist baz ( 1864 if exist bazro ( 1865 echo read-only files are moveable 1866 move bazro baz > nul 2>&1 1867 ) 1868) else ( 1869 echo read-only file not moved! 1870) 1871attrib -r baz 1872mkdir rep 1873move baz rep > nul 2>&1 1874if not exist baz ( 1875 if exist rep\baz ( 1876 echo file moved in subdirectory 1877 ) 1878) 1879call :setError 0 1880move rep\baz . > nul 2>&1 1881move /Y baz baz > nul 2>&1 1882if errorlevel 1 ( 1883 echo moving a file to itself should be a no-op! 1884) else ( 1885 echo moving a file to itself is a no-op 1886) 1887echo ErrorLevel: %ErrorLevel% 1888call :setError 0 1889del baz 1890echo --- directory move 1891mkdir foo\bar 1892mkdir baz 1893echo baz2>baz\baz2 1894move baz foo\bar > nul 2>&1 1895if not exist baz ( 1896 if exist foo\bar\baz\baz2 ( 1897 echo simple directory move succeeded 1898 ) 1899) 1900call :setError 0 1901mkdir baz 1902move baz baz > nul 2>&1 1903echo moving a directory to itself gives error; errlevel %ErrorLevel% 1904echo ------ dir in dir move 1905rd /s/q foo 1906mkdir foo bar 1907echo foo2>foo\foo2 1908echo bar2>bar\bar2 1909move foo bar > nul 2>&1 1910if not exist foo ( 1911 if exist bar ( 1912 dir /b /ad bar 1913 dir /b /a-d bar 1914 dir /b bar\foo 1915 ) 1916) 1917cd .. & rd /s/q foobar 1918 1919echo ------------ Testing mkdir ------------ 1920call :setError 0 1921echo --- md and mkdir are synonymous 1922mkdir foobar 1923echo %ErrorLevel% 1924rmdir foobar 1925md foobar 1926echo %ErrorLevel% 1927rmdir foobar 1928echo --- creating an already existing directory/file must fail 1929mkdir foobar 1930md foobar 1931echo %ErrorLevel% 1932rmdir foobar 1933echo > foobar 1934mkdir foobar 1935echo %ErrorLevel% 1936del foobar 1937echo --- multilevel path creation 1938mkdir foo 1939echo %ErrorLevel% 1940mkdir foo\bar\baz 1941echo %ErrorLevel% 1942cd foo 1943echo %ErrorLevel% 1944cd bar 1945echo %ErrorLevel% 1946cd baz 1947echo %ErrorLevel% 1948echo > ..\..\bar2 1949mkdir ..\..\..\foo\bar2 1950echo %ErrorLevel% 1951del ..\..\bar2 1952mkdir ..\..\..\foo\bar2 1953echo %ErrorLevel% 1954rmdir ..\..\..\foo\bar2 1955cd .. 1956rmdir baz 1957cd .. 1958rmdir bar 1959cd .. 1960rmdir foo 1961echo %ErrorLevel% 1962echo --- trailing backslashes 1963mkdir foo\\\\ 1964echo %ErrorLevel% 1965if exist foo (rmdir foo & echo dir created 1966) else ( echo dir not created ) 1967echo %ErrorLevel% 1968echo --- invalid chars 1969mkdir ? 1970echo mkdir ? gives errorlevel %ErrorLevel% 1971call :setError 0 1972mkdir ?\foo 1973echo mkdir ?\foo gives errorlevel %ErrorLevel% 1974call :setError 0 1975mkdir foo\? 1976echo mkdir foo\? gives errorlevel %ErrorLevel% 1977if exist foo (rmdir foo & echo ok, foo created 1978) else ( echo foo not created ) 1979call :setError 0 1980mkdir foo\bar\? 1981echo mkdir foo\bar\? gives errorlevel %ErrorLevel% 1982call :setError 0 1983if not exist foo ( 1984 echo bad, foo not created 1985) else ( 1986 cd foo 1987 if exist bar ( 1988 echo ok, foo\bar created 1989 rmdir bar 1990 ) 1991 cd .. 1992 rmdir foo 1993) 1994echo --- multiple directories at once 1995mkdir foobaz & cd foobaz 1996mkdir foo bar\baz foobar "bazbaz" .\"zabzab" 1997if exist foo (echo foo created) else echo foo not created! 1998if exist bar (echo bar created) else echo bar not created! 1999if exist foobar (echo foobar created) else echo foobar not created! 2000if exist bar\baz (echo bar\baz created) else echo bar\baz not created! 2001if exist bazbaz (echo bazbaz created) else echo bazbaz not created! 2002if exist zabzab (echo zabzab created) else echo zabzab not created! 2003cd .. & rd /s/q foobaz 2004call :setError 0 2005mkdir foo\* 2006echo mkdir foo\* errorlevel %ErrorLevel% 2007if exist foo (rmdir foo & echo ok, foo created 2008) else ( echo bad, foo not created ) 2009 2010echo ------------ Testing rmdir ------------ 2011call :setError 0 2012rem rd and rmdir are synonymous 2013mkdir foobar 2014rmdir foobar 2015echo %ErrorLevel% 2016if not exist foobar echo dir removed 2017mkdir foobar 2018rd foobar 2019echo %ErrorLevel% 2020if not exist foobar echo dir removed 2021rem Removing nonexistent directory 2022rmdir foobar 2023echo %ErrorLevel% 2024rem Removing single-level directories 2025echo > foo 2026rmdir foo 2027echo %ErrorLevel% 2028if exist foo echo file not removed 2029del foo 2030mkdir foo 2031echo > foo\bar 2032rmdir foo 2033echo %ErrorLevel% 2034if exist foo echo non-empty dir not removed 2035del foo\bar 2036mkdir foo\bar 2037rmdir foo 2038echo %ErrorLevel% 2039if exist foo echo non-empty dir not removed 2040rmdir foo\bar 2041rmdir foo 2042rem Recursive rmdir 2043mkdir foo\bar\baz 2044rmdir /s /Q foo 2045if not exist foo ( 2046 echo recursive rmdir succeeded 2047) else ( 2048 rd foo\bar\baz 2049 rd foo\bar 2050 rd foo 2051) 2052mkdir foo\bar\baz 2053echo foo > foo\bar\brol 2054rmdir /s /Q foo 2>&1 2055if not exist foo ( 2056 echo recursive rmdir succeeded 2057) else ( 2058 rd foo\bar\baz 2059 del foo\bar\brol 2060 rd foo\bar 2061 rd foo 2062) 2063rem multiples directories at once 2064mkdir foobaz & cd foobaz 2065mkdir foo 2066mkdir bar\baz 2067mkdir foobar 2068rd /s/q foo bar foobar 2069if not exist foo (echo foo removed) else echo foo not removed! 2070if not exist bar (echo bar removed) else echo bar not removed! 2071if not exist foobar (echo foobar removed) else echo foobar not removed! 2072if not exist bar\baz (echo bar\baz removed) else echo bar\baz not removed! 2073cd .. & rd /s/q foobaz 2074 2075echo ------------ Testing pushd/popd ------------ 2076cd 2077echo --- popd is no-op when dir stack is empty 2078popd 2079cd 2080echo --- pushing non-existing dir 2081pushd foobar 2082cd 2083echo --- basic behaviour 2084mkdir foobar\baz 2085pushd foobar 2086cd 2087popd 2088cd 2089pushd foobar 2090pushd baz 2091cd 2092popd 2093cd 2094pushd baz 2095popd 2096cd 2097popd 2098cd 2099pushd . 2100cd foobar\baz 2101pushd .. 2102cd 2103popd 2104popd 2105cd 2106rd /s/q foobar 2107 2108echo ------------ Testing attrib ------------ 2109rem FIXME Add tests for archive, hidden and system attributes + mixed attributes modifications 2110mkdir foobar & cd foobar 2111echo foo original contents> foo 2112attrib foo 2113echo > bar 2114echo --- read-only attribute 2115rem Read-only files cannot be altered or deleted, unless forced 2116attrib +R foo 2117attrib foo 2118dir /Ar /B 2119echo bar>> foo 2120type foo 2121del foo > NUL 2>&1 2122if exist foo ( 2123 echo Read-only file not deleted 2124) else ( 2125 echo Should not delete read-only file! 2126) 2127del /F foo 2128if not exist foo ( 2129 echo Read-only file forcibly deleted 2130) else ( 2131 echo Should delete read-only file with del /F! 2132 attrib -r foo 2133 del foo 2134) 2135cd .. & rd /s/q foobar 2136echo --- recursive behaviour 2137mkdir foobar\baz & cd foobar 2138echo > level1 2139echo > whatever 2140echo > baz\level2 2141attrib baz\level2 2142cd .. 2143attrib +R l*vel? /S > nul 2>&1 2144cd foobar 2145attrib level1 2146attrib baz\level2 2147echo > bar 2148attrib bar 2149cd .. & rd /s/q foobar 2150echo --- folders processing 2151mkdir foobar 2152attrib foobar 2153cd foobar 2154mkdir baz 2155echo toto> baz\toto 2156attrib +r baz /s /d > nul 2>&1 2157attrib baz 2158attrib baz\toto 2159echo lulu>>baz\toto 2160type baz\toto 2161echo > baz\lala 2162rem Oddly windows allows file creation in a read-only directory... 2163if exist baz\lala (echo file created in read-only dir) else echo file not created 2164cd .. & rd /s/q foobar 2165 2166echo ------------ Testing assoc ------------ 2167rem Modifying associations requires some privileges... 2168net session >nul 2>&1 2169if errorlevel 1 goto :SkipAssoc 2170 2171rem FIXME Can't test error messages in the current test system, so we have to use some kludges 2172rem FIXME Revise once || conditional execution is fixed 2173mkdir foobar & cd foobar 2174echo --- setting association 2175assoc .foo > baz 2176type baz 2177echo --- 2178 2179assoc .foo=bar 2180assoc .foo 2181 2182rem association set system-wide 2183echo @echo off> tmp.cmd 2184echo echo +++>> tmp.cmd 2185echo assoc .foo>> tmp.cmd 2186cmd /c tmp.cmd 2187 2188echo --- resetting association 2189assoc .foo= 2190assoc .foo > baz 2191type baz 2192echo --- 2193 2194rem association removal set system-wide 2195cmd /c tmp.cmd > baz 2196type baz 2197echo --- 2198cd .. & rd /s/q foobar 2199goto ContinueFType 2200:SkipAssoc 2201echo --- setting association 2202echo --- 2203echo .foo=bar 2204echo .foo=bar 2205echo +++ 2206echo .foo=bar 2207echo --- resetting association 2208echo --- 2209echo +++ 2210echo --- 2211 2212 2213:ContinueFType 2214echo ------------ Testing ftype ------------ 2215rem Modifying associations requires some privileges... 2216net session >nul 2>&1 2217if errorlevel 1 goto :SkipFType 2218rem FIXME Can't test error messages in the current test system, so we have to use some kludges 2219rem FIXME Revise once || conditional execution is fixed 2220mkdir foobar & cd foobar 2221echo --- setting association 2222ftype footype> baz 2223type baz 2224echo --- 2225 2226ftype footype=foo_opencmd 2227assoc .foo=footype 2228ftype footype 2229 2230rem association set system-wide 2231echo @echo off> tmp.cmd 2232echo echo +++>> tmp.cmd 2233echo ftype footype>> tmp.cmd 2234cmd /c tmp.cmd 2235 2236echo --- resetting association 2237assoc .foo= 2238 2239rem Removing a file type association doesn't work on XP due to a bug, so a workaround is needed 2240setlocal EnableDelayedExpansion 2241set WINE_FOO=original value 2242ftype footype= 2243ftype footype > baz 2244for /F %%i in ('type baz') do (set WINE_FOO=buggyXP) 2245rem Resetting actually works on wine/NT4, but is reported as failing due to the peculiar test (and non-support for EnabledDelayedExpansion) 2246rem FIXME Revisit once a grep-like program like ftype is implemented 2247rem (e.g. to check baz's size using dir /b instead) 2248echo !WINE_FOO! 2249 2250rem cleanup registry 2251echo REGEDIT4> regCleanup.reg 2252echo.>> regCleanup.reg 2253echo [-HKEY_CLASSES_ROOT\footype]>> regCleanup.reg 2254regedit /s regCleanup.reg 2255set WINE_FOO= 2256endlocal 2257cd .. & rd /s/q foobar 2258goto ContinueCall 2259:SkipFType 2260echo --- setting association 2261echo --- 2262echo footype=foo_opencmd 2263echo .foo=footype 2264echo footype=foo_opencmd 2265echo +++ 2266echo footype=foo_opencmd 2267echo --- resetting association 2268echo original value 2269 2270:ContinueCall 2271echo ------------ Testing CALL ------------ 2272mkdir foobar & cd foobar 2273echo --- external script 2274echo echo foo %%1> foo.cmd 2275call foo 2276call foo.cmd 8 2277echo echo %%1 %%2 > foo.cmd 2278call foo.cmd foo 2279call foo.cmd foo bar 2280call foo.cmd foo "" 2281call foo.cmd "" bar 2282call foo.cmd foo '' 2283call foo.cmd '' bar 2284del foo.cmd 2285 2286echo --- internal routines 2287call :testRoutine :testRoutine 2288goto :endTestRoutine 2289:testRoutine 2290echo bar %1 2291goto :eof 2292:endTestRoutine 2293 2294call :testRoutineArgs foo 2295call :testRoutineArgs foo bar 2296call :testRoutineArgs foo "" 2297call :testRoutineArgs "" bar 2298call :testRoutineArgs foo '' 2299call :testRoutineArgs '' bar 2300goto :endTestRoutineArgs 2301:testRoutineArgs 2302echo %1 %2 2303goto :eof 2304:endTestRoutineArgs 2305 2306echo --- with builtins 2307call mkdir foo 2308echo %ErrorLevel% 2309if exist foo (echo foo created) else echo foo should exist! 2310rmdir foo 2311set WINE_FOOBAZ_VAR=foobaz 2312call echo Should expand %WINE_FOOBAZ_VAR% 2313set WINE_FOOBAZ_VAR= 2314echo>batfile 2315call dir /b 2316echo>robinfile 2317if 1==1 call del batfile 2318dir /b 2319if exist batfile echo batfile shouldn't exist 2320rem ... but not for 'if' or 'for' 2321call if 1==1 echo bar 2> nul 2322echo %ErrorLevel% 2323call :setError 0 2324call for %%i in (foo bar baz) do echo %%i 2> nul 2325echo %ErrorLevel% 2326rem First look for programs in the path before trying a builtin 2327echo echo non-builtin dir> dir.cmd 2328call dir /b 2329del dir.cmd 2330rem The below line equates to call (, which does nothing, then the 2331rem subsequent lines are executed. 2332call ( 2333 echo Line one 2334 echo Line two 2335) 2336rem The below line equates to call if, which always fails, then the 2337rem subsequent lines are executed. Note cmd.exe swallows all lines 2338rem starting with ) 2339call if 1==1 ( 2340 echo Get if 2341) else ( 2342 echo ... and else! 2343) 2344call call call echo passed 2345cd .. & rd /s/q foobar 2346 2347echo ------------ Testing SHIFT ------------ 2348 2349call :shiftFun p1 p2 p3 p4 p5 2350goto :endShiftFun 2351 2352:shiftFun 2353echo '%1' '%2' '%3' '%4' '%5' 2354shift 2355echo '%1' '%2' '%3' '%4' '%5' 2356shift@tab@ /1 2357echo '%1' '%2' '%3' '%4' '%5' 2358shift /2 2359echo '%1' '%2' '%3' '%4' '%5' 2360shift /-1 2361echo '%1' '%2' '%3' '%4' '%5' 2362shift /0 2363echo '%1' '%2' '%3' '%4' '%5' 2364goto :eof 2365:endShiftFun 2366 2367echo ------------ Testing cmd invocation ------------ 2368rem FIXME: only a stub ATM 2369echo --- a batch file can delete itself 2370echo del foo.cmd>foo.cmd 2371cmd /q /c foo.cmd 2372if not exist foo.cmd ( 2373 echo file correctly deleted 2374) else ( 2375 echo file should be deleted! 2376 del foo.cmd 2377) 2378echo --- a batch file can alter itself 2379echo echo bar^>foo.cmd>foo.cmd 2380cmd /q /c foo.cmd > NUL 2>&1 2381if exist foo.cmd ( 2382 type foo.cmd 2383 del foo.cmd 2384) else ( 2385 echo file not created! 2386) 2387 2388echo ---------- Testing copy 2389md foobar2 2390cd foobar2 2391rem Note echo adds 0x0d 0x0a on the end of the line in the file 2392echo AAA> file1 2393echo BBBBBB> file2 2394echo CCCCCCCCC> file3 2395md dir1 2396goto :testcopy 2397 2398:CheckExist 2399if exist "%1" ( 2400 echo Passed: Found expected %1 2401) else ( 2402 echo Failed: Did not find expected %1 2403) 2404del /q "%1" >nul 2>&1 2405shift 2406if not "%1"=="" goto :CheckExist 2407goto :eof 2408 2409:CheckNotExist 2410if not exist "%1" ( 2411 echo Passed: Did not find %1 2412) else ( 2413 echo Failed: Unexpectedly found %1 2414 del /q "%1" >nul 2>&1 2415) 2416shift 2417if not "%1"=="" goto :CheckNotExist 2418goto :eof 2419 2420rem Note: No way to check file size on NT4 so skip the test 2421:CheckFileSize 2422if not exist "%1" ( 2423 echo Failed: File missing when requested filesize check [%2] 2424 goto :ContinueFileSizeChecks 2425) 2426for %%i in (%1) do set WINE_filesize=%%~zi 2427if "%WINE_filesize%"=="%2" ( 2428 echo Passed: file size check on %1 [%WINE_filesize%] 2429) else ( 2430 if "%WINE_filesize%"=="%%~zi" ( 2431 echo Skipping file size check on NT4 2432 ) else ( 2433 echo Failed: file size check on %1 [%WINE_filesize% != %2] 2434 ) 2435) 2436:ContinueFileSizeChecks 2437shift 2438shift 2439if not "%1"=="" goto :CheckFileSize 2440goto :eof 2441 2442:testcopy 2443 2444rem ----------------------- 2445rem Simple single file copy 2446rem ----------------------- 2447rem Simple single file copy, normally used syntax 2448copy file1 dummy.file >nul 2>&1 2449if errorlevel 1 echo Incorrect errorlevel 2450call :CheckExist dummy.file 2451 2452rem Simple single file copy, destination supplied as two forms of directory 2453copy file1 dir1 >nul 2>&1 2454if errorlevel 1 echo Incorrect errorlevel 2455call :CheckExist dir1\file1 2456 2457copy file1 dir1\ >nul 2>&1 2458if errorlevel 1 echo Incorrect errorlevel 2459call :CheckExist dir1\file1 2460 2461rem Simple single file copy, destination supplied as fully qualified destination 2462copy file1 dir1\file99 >nul 2>&1 2463if errorlevel 1 echo Incorrect errorlevel 2464call :CheckExist dir1\file99 2465 2466rem Simple single file copy, destination not supplied 2467cd dir1 2468copy ..\file1 >nul 2>&1 2469if errorlevel 1 echo Incorrect errorlevel 2470call :CheckExist file1 2471cd .. 2472 2473rem Simple single file copy, destination supplied as nonexistent directory 2474copy file1 dir2\ >nul 2>&1 2475if not errorlevel 1 echo Incorrect errorlevel 2476call :CheckNotExist dir2 dir2\file1 2477 2478rem ----------------------- 2479rem Wildcarded copy 2480rem ----------------------- 2481rem Simple single file copy, destination supplied as two forms of directory 2482copy file? dir1 >nul 2>&1 2483if errorlevel 1 echo Incorrect errorlevel 2484call :CheckExist dir1\file1 dir1\file2 dir1\file3 2485 2486copy file* dir1\ >nul 2>&1 2487if errorlevel 1 echo Incorrect errorlevel 2488call :CheckExist dir1\file1 dir1\file2 dir1\file3 2489 2490rem Simple single file copy, destination not supplied 2491cd dir1 2492copy ..\file*.* >nul 2>&1 2493if errorlevel 1 echo Incorrect errorlevel 2494call :CheckExist file1 file2 file3 2495cd .. 2496 2497rem Simple wildcarded file copy, destination supplied as nonexistent directory 2498copy file? dir2\ >nul 2>&1 2499if not errorlevel 1 echo Incorrect errorlevel 2500call :CheckNotExist dir2 dir2\file1 dir2\file2 dir2\file3 2501 2502rem ------------------------------------------------ 2503rem Confirm overwrite works (cannot test prompting!) 2504rem ------------------------------------------------ 2505copy file1 testfile >nul 2>&1 2506copy /y file2 testfile >nul 2>&1 2507call :CheckExist testfile 2508 2509rem ------------------------------------------------ 2510rem Test concatenation 2511rem ------------------------------------------------ 2512rem simple case, no wildcards 2513copy file1+file2 testfile >nul 2>&1 2514if errorlevel 1 echo Incorrect errorlevel 2515call :CheckExist testfile 2516 2517rem simple case, wildcards, no concatenation 2518copy file* testfile >nul 2>&1 2519if errorlevel 1 echo Incorrect errorlevel 2520call :CheckExist testfile 2521 2522rem simple case, wildcards, and concatenation 2523echo ddddd > fred 2524copy file*+fred testfile >nul 2>&1 2525if errorlevel 1 echo Incorrect errorlevel 2526call :CheckExist testfile 2527 2528rem simple case, wildcards, and concatenation 2529copy fred+file* testfile >nul 2>&1 2530if errorlevel 1 echo Incorrect errorlevel 2531call :CheckExist testfile 2532 2533rem Calculate destination name 2534copy fred+file* dir1 >nul 2>&1 2535if errorlevel 1 echo Incorrect errorlevel 2536call :CheckExist dir1\fred 2537 2538rem Calculate destination name 2539copy fred+file* dir1\ >nul 2>&1 2540if errorlevel 1 echo Incorrect errorlevel 2541call :CheckExist dir1\fred 2542 2543rem Calculate destination name (none supplied) 2544cd dir1 2545copy ..\fred+..\file* >nul 2>&1 2546if errorlevel 1 echo Incorrect errorlevel 2547call :CheckExist fred 2548 2549copy ..\fr*+..\file1 >nul 2>&1 2550if errorlevel 1 echo Incorrect errorlevel 2551call :CheckExist fred 2552cd .. 2553 2554rem ****************************************************************** 2555rem ASCII and BINARY tests 2556rem Note: hard coded numbers deliberate because need to ensure whether 2557rem an additional EOF has been added or not. There is no way to handle 2558rem EOFs in batch, so assume if a single byte appears, it's an EOF! 2559rem ****************************************************************** 2560 2561rem Confirm original sizes of file1,2,3 2562call :CheckFileSize file1 5 file2 8 file3 11 2563 2564cd dir1 2565 2566rem ---------------------------------------------- 2567rem Show concatenation defaults copy to ascii mode 2568rem ---------------------------------------------- 2569rem Simple default copy source to destination (should not append EOF 5) 2570copy ..\file1 file1_default >nul 2>&1 2571call :CheckFileSize file1_default 5 2572 2573rem Simple binary copy source to destination (should not append EOF 5) 2574copy /b ..\file1 file1_default2 >nul 2>&1 2575call :CheckFileSize file1_default2 5 2576 2577rem Simple ascii copy source to destination (should append EOF 5+1, 8+1, 11+1) 2578copy /a ..\file1 file1_plus_eof >nul 2>&1 2579call :CheckFileSize file1_plus_eof 6 2580copy /a ..\file2 file2_plus_eof >nul 2>&1 2581call :CheckFileSize file2_plus_eof 9 2582copy /a ..\file3 file3_plus_eof >nul 2>&1 2583call :CheckFileSize file3_plus_eof 12 2584 2585rem Concat 2 files, ascii mode - (only one EOF on the end 5+8+1) 2586copy /a ..\file1+..\file2 file12_plus_eof >nul 2>&1 2587call :CheckFileSize file12_plus_eof 14 2588 2589rem Concat 2 files, binary mode - (no EOF on the end 5+8) 2590copy /b ..\file1+..\file2 file12_no_eof >nul 2>&1 2591call :CheckFileSize file12_no_eof 13 2592 2593rem Concat 2 files, default mode - (one EOF on the end 5+8+1) 2594copy ..\file1+..\file2 file12_eof2 >nul 2>&1 2595call :CheckFileSize file12_eof2 14 2596 2597rem Test copying when destination is one of the sources. 2598rem Concat file1+file2+file3 into file1, should produce file1+file2+file3 = 24 2599copy /y ..\file? .\ >nul 2>&1 2600copy /y /b file1+file2+file3 file1 >nul 2>&1 2601call :CheckFileSize file1 24 2602 2603rem Concat file1+file2+file3 into file2, should produce file1+file3 = 16 2604copy /y ..\file? .\ >nul 2>&1 2605copy /y /b file1+file2+file3 file2 >nul 2>&1 2606call :CheckFileSize file2 16 2607 2608rem Concat file1+file2+file3 into file3, should produce file1+file2 = 13 2609copy /y ..\file? .\ >nul 2>&1 2610copy /y /b file1+file2+file3 file3 >nul 2>&1 2611call :CheckFileSize file3 13 2612 2613rem -------------------------------------------------------------- 2614rem Show ascii source copy stops at first EOF, binary does the lot 2615rem -------------------------------------------------------------- 2616copy file1_plus_eof /b file1_binary_srccopy /b >nul 2>&1 2617call :CheckFileSize file1_binary_srccopy 6 2618 2619copy file1_plus_eof /a file1_ascii_srccopy /b >nul 2>&1 2620call :CheckFileSize file1_ascii_srccopy 5 2621 2622rem -------------------------------------------------------------- 2623rem Show results of concatenating files (ending in EOFs) and /a /b 2624rem -------------------------------------------------------------- 2625 2626rem Default and ascii copy reads as ascii, stripping EOFs, so 6-1 + 9-1 + 12-1 + 1 2627copy file1_plus_eof+file2_plus_eof+file3_plus_eof file123_default_copy >nul 2>&1 2628call :CheckFileSize file123_default_copy 25 2629copy /a file1_plus_eof+file2_plus_eof+file3_plus_eof file123_ascii_copy >nul 2>&1 2630call :CheckFileSize file123_ascii_copy 25 2631 2632rem In binary mode, we get 3 eofs, so 6 + 9 + 12 = 27 2633copy /b file1_plus_eof + file2_plus_eof + file3_plus_eof file123_binary_copy >nul 2>&1 2634call :CheckFileSize file123_binary_copy 27 2635 2636rem We can select which we want the eofs from by postfixing it with /a or /b 2637rem so here have first and third with eof, second as ascii 6 + 9-1 + 12 2638copy file1_plus_eof /b + file2_plus_eof /a + file3_plus_eof /b file123_mixed_copy1 >nul 2>&1 2639call :CheckFileSize file123_mixed_copy1 26 2640 2641rem By postfixing the destination with /a, we ask for an ascii destination which appends EOF 2642rem so here have first and third with eof, second as ascii 6 + 9-1 + 12 + extra EOF 2643rem Note the delta between this and the previous one also shows that the destination 2644rem ascii/binary is inherited from the last /a or /b on the line 2645copy file1_plus_eof /b + file2_plus_eof /a + file3_plus_eof /b file123_mixed_copy2 /a >nul 2>&1 2646call :CheckFileSize file123_mixed_copy2 27 2647 2648rem so here have second with eof, first and third as ascii 6-1 + 9 + 12-1 2649rem Note the delta between the next two also shows that the destination ascii/binary is 2650rem inherited from the last /a or /b on the line, so the first has an extra EOF 2651copy file1_plus_eof /a + file2_plus_eof /b + file3_plus_eof /a file123_mixed_copy3 >nul 2>&1 2652call :CheckFileSize file123_mixed_copy3 26 2653copy file1_plus_eof /a + file2_plus_eof /b + file3_plus_eof /a file123_mixed_copy4 /b >nul 2>&1 2654call :CheckFileSize file123_mixed_copy4 25 2655 2656rem ------------------------------------------------------------------------------------------- 2657rem This shows when concatenating, an ascii destination always adds on an EOF but when we 2658rem are not concatenating, it's a direct copy regardless of destination if being read as binary 2659rem ------------------------------------------------------------------------------------------- 2660 2661rem All 3 have eof's, plus an extra = 6 + 9 + 12 + eof 2662copy /b file1_plus_eof + file2_plus_eof + file3_plus_eof file123_mixed_copy5 /a >nul 2>&1 2663call :CheckFileSize file123_mixed_copy5 28 2664 2665rem All 2 have eof's, plus an extra = 6 + 12 + eof 2666copy /b file1_plus_eof + file3_plus_eof file123_mixed_copy6 /a >nul 2>&1 2667call :CheckFileSize file123_mixed_copy6 19 2668 2669rem One file has EOF, but doesn't get an extra one, i.e. 6 2670copy /b file1_plus_eof file123_mixed_copy7 /a >nul 2>&1 2671call :CheckFileSize file123_mixed_copy7 6 2672 2673rem Syntax means concatenate so ascii destination kicks in 2674copy /b file1_plus_eof* file123_mixed_copy8 /a >nul 2>&1 2675call :CheckFileSize file123_mixed_copy8 7 2676 2677del *.* /q 2678cd .. 2679 2680rem --------------------------------------- 2681rem Error combinations 2682rem --------------------------------------- 2683rem Specify source directory but name is a file 2684call :setError 0 2685copy file1\ dir1\ >NUL 2>&1 2686if errorlevel 1 echo Passed: errorlevel invalid check 1 2687if not errorlevel 1 echo Failed: errorlevel invalid check 1 2688call :CheckNotExist dir1\file1 2689 2690rem Overwrite same file 2691call :setError 0 2692copy file1 file1 >NUL 2>&1 2693if errorlevel 1 echo Passed: errorlevel invalid check 2 2694if not errorlevel 1 echo Failed: errorlevel invalid check 2 2695 2696rem Supply same file identified as a directory 2697call :setError 0 2698copy file1 file1\ >NUL 2>&1 2699if errorlevel 1 echo Passed: errorlevel invalid check 3 2700if not errorlevel 1 echo Failed: errorlevel invalid check 3 2701 2702cd .. 2703rd foobar2 /s /q 2704 2705echo ------------ Testing setlocal/endlocal ------------ 2706call :setError 0 2707rem Note: setlocal EnableDelayedExpansion already tested in the variable delayed expansion test section 2708mkdir foobar & cd foobar 2709echo --- enable/disable extensions 2710setlocal DisableEXTensions 2711echo ErrLev: %ErrorLevel% 2712endlocal 2713echo ErrLev: %ErrorLevel% 2714echo @echo off> tmp.cmd 2715echo echo ErrLev: %%ErrorLevel%%>> tmp.cmd 2716rem Enabled by default 2717cmd /C tmp.cmd 2718cmd /E:OfF /C tmp.cmd 2719cmd /e:oN /C tmp.cmd 2720 2721rem FIXME: creating file before setting envvar value to prevent parsing-time evaluation (due to EnableDelayedExpansion not being implemented/available yet) 2722echo --- setlocal with corresponding endlocal 2723rem %CD% does not work on NT4 so use the following workaround 2724for /d %%i in (.) do set WINE_CURDIR=%%~dpnxi 2725echo @echo off> test.cmd 2726echo echo %%WINE_VAR%%>> test.cmd 2727echo setlocal>> test.cmd 2728echo set WINE_VAR=localval>> test.cmd 2729echo md foobar2>> test.cmd 2730echo cd foobar2>> test.cmd 2731echo echo %%WINE_VAR%%>> test.cmd 2732echo for /d %%%%i in (.) do echo %%%%~dpnxi>> test.cmd 2733echo endlocal>> test.cmd 2734echo echo %%WINE_VAR%%>> test.cmd 2735echo for /d %%%%i in (.) do echo %%%%~dpnxi>> test.cmd 2736set WINE_VAR=globalval 2737call test.cmd 2738echo %WINE_VAR% 2739for /d %%i in (.) do echo %%~dpnxi 2740cd /d %WINE_CURDIR% 2741rd foobar2 2742set WINE_VAR= 2743echo --- setlocal with no corresponding endlocal 2744echo @echo off> test.cmd 2745echo echo %%WINE_VAR%%>> test.cmd 2746echo setlocal>> test.cmd 2747echo set WINE_VAR=localval>> test.cmd 2748echo md foobar2>> test.cmd 2749echo cd foobar2>> test.cmd 2750echo echo %%WINE_VAR%%>> test.cmd 2751echo for /d %%%%i in (.) do echo %%%%~dpnxi>> test.cmd 2752set WINE_VAR=globalval 2753rem %CD% does not work on NT4 so use the following workaround 2754for /d %%i in (.) do set WINE_CURDIR=%%~dpnxi 2755call test.cmd 2756echo %WINE_VAR% 2757for /d %%i in (.) do echo %%~dpnxi 2758cd /d %WINE_CURDIR% 2759rd foobar2 2760set WINE_VAR= 2761echo --- setlocal within same batch program 2762set WINE_var1=one 2763set WINE_var2= 2764set WINE_var3= 2765rem %CD% does not work on NT4 so use the following workaround 2766for /d %%i in (.) do set WINE_CURDIR=%%~dpnxi 2767setlocal 2768set WINE_var2=two 2769mkdir foobar2 2770cd foobar2 2771setlocal 2772set WINE_var3=three 2773if "%WINE_var1%"=="one" echo Var1 ok 1 2774if "%WINE_var2%"=="two" echo Var2 ok 2 2775if "%WINE_var3%"=="three" echo Var3 ok 3 2776for /d %%i in (.) do set WINE_curdir2=%%~dpnxi 2777if "%WINE_curdir2%"=="%WINE_CURDIR%\foobar2" echo Directory is ok 1 2778endlocal 2779if "%WINE_var1%"=="one" echo Var1 ok 1 2780if "%WINE_var2%"=="two" echo Var2 ok 2 2781if "%WINE_var3%"=="" echo Var3 ok 3 2782for /d %%i in (.) do set WINE_curdir2=%%~dpnxi 2783if "%WINE_curdir2%"=="%WINE_CURDIR%\foobar2" echo Directory is ok 2 2784endlocal 2785if "%WINE_var1%"=="one" echo Var1 ok 1 2786if "%WINE_var2%"=="" echo Var2 ok 2 2787if "%WINE_var3%"=="" echo Var3 ok 3 2788for /d %%i in (.) do set WINE_curdir2=%%~dpnxi 2789if "%WINE_curdir2%"=="%WINE_CURDIR%" echo Directory is ok 3 2790rd foobar2 /s /q 2791set WINE_var1= 2792 2793echo --- Mismatched set and end locals 2794mkdir foodir2 2>nul 2795mkdir foodir3 2>nul 2796mkdir foodir4 2>nul 2797rem %CD% does not work on NT4 so use the following workaround 2798for /d %%i in (.) do set WINE_curdir=%%~dpnxi 2799 2800echo @echo off> 2set1end.cmd 2801echo echo %%WINE_var%%>> 2set1end.cmd 2802echo setlocal>> 2set1end.cmd 2803echo set WINE_VAR=2set1endvalue1>> 2set1end.cmd 2804echo cd ..\foodir3>> 2set1end.cmd 2805echo setlocal>> 2set1end.cmd 2806echo set WINE_VAR=2set1endvalue2>> 2set1end.cmd 2807echo cd ..\foodir4>> 2set1end.cmd 2808echo endlocal>> 2set1end.cmd 2809echo echo %%WINE_var%%>> 2set1end.cmd 2810echo for /d %%%%i in (.) do echo %%%%~dpnxi>> 2set1end.cmd 2811 2812echo @echo off> 1set2end.cmd 2813echo echo %%WINE_var%%>> 1set2end.cmd 2814echo setlocal>> 1set2end.cmd 2815echo set WINE_VAR=1set2endvalue1>> 1set2end.cmd 2816echo cd ..\foodir3>> 1set2end.cmd 2817echo endlocal>> 1set2end.cmd 2818echo echo %%WINE_var%%>> 1set2end.cmd 2819echo for /d %%%%i in (.) do echo %%%%~dpnxi>> 1set2end.cmd 2820echo endlocal>> 1set2end.cmd 2821echo echo %%WINE_var%%>> 1set2end.cmd 2822echo for /d %%%%i in (.) do echo %%%%~dpnxi>> 1set2end.cmd 2823 2824echo --- Extra setlocal in called batch 2825set WINE_VAR=value1 2826rem -- setlocal1 == this batch, should never be used inside a called routine 2827setlocal 2828set WINE_var=value2 2829cd foodir2 2830call "%WINE_CURDIR%\2set1end.cmd" 2831echo Finished: 2832echo %WINE_VAR% 2833for /d %%i in (.) do echo %%~dpnxi 2834endlocal 2835echo %WINE_VAR% 2836for /d %%i in (.) do echo %%~dpnxi 2837cd /d %WINE_CURDIR% 2838 2839echo --- Extra endlocal in called batch 2840set WINE_VAR=value1 2841rem -- setlocal1 == this batch, should never be used inside a called routine 2842setlocal 2843set WINE_var=value2 2844cd foodir2 2845call "%WINE_CURDIR%\1set2end.cmd" 2846echo Finished: 2847echo %WINE_VAR% 2848for /d %%i in (.) do echo %%~dpnxi 2849endlocal 2850echo %WINE_VAR% 2851for /d %%i in (.) do echo %%~dpnxi 2852cd /d %WINE_CURDIR% 2853 2854echo --- endlocal in called function rather than batch pgm is ineffective 2855@echo off 2856set WINE_var=1 2857set WINE_var2=1 2858setlocal 2859set WINE_var=2 2860call :endlocalroutine 2861echo %WINE_var% 2862endlocal 2863echo %WINE_var% 2864goto :endlocalfinished 2865:endlocalroutine 2866echo %WINE_var% 2867endlocal 2868echo %WINE_var% 2869setlocal 2870set WINE_var2=2 2871endlocal 2872echo %WINE_var2% 2873endlocal 2874echo %WINE_var% 2875echo %WINE_var2% 2876goto :eof 2877:endlocalfinished 2878echo %WINE_var% 2879 2880set WINE_var= 2881set WINE_var2= 2882cd .. & rd /q/s foobar 2883 2884echo ------------ Testing Errorlevel ------------ 2885rem WARNING: Do *not* add tests using ErrorLevel after this section 2886should_not_exist 2> nul > nul 2887echo %ErrorLevel% 2888rem nt 4.0 doesn't really support a way of setting errorlevel, so this is weak 2889rem See http://www.robvanderwoude.com/exit.php 2890call :setError 1 2891echo %ErrorLevel% 2892if errorlevel 2 echo errorlevel too high, bad 2893if errorlevel 1 echo errorlevel just right, good 2894if errorlevel 01 echo errorlevel with leading zero just right, good 2895if errorlevel -1 echo errorlevel with negative number OK 2896if errorlevel 0x1 echo hexa should not be recognized! 2897if errorlevel 1a echo invalid error level recognized! 2898call :setError 0 2899echo abc%ErrorLevel%def 2900if errorlevel 1 echo errorlevel nonzero, bad 2901if not errorlevel 1 echo errorlevel zero, good 2902if not errorlevel 0x1 echo hexa should not be recognized! 2903if not errorlevel 1a echo invalid error level recognized! 2904rem Now verify that setting a real variable hides its magic variable 2905set errorlevel=7 2906echo %ErrorLevel% should be 7 2907if errorlevel 7 echo setting var worked too well, bad 2908call :setError 3 2909echo %ErrorLevel% should still be 7 2910 2911echo ------------ Testing GOTO ------------ 2912if a==a goto dest1 2913echo FAILURE at dest 1 2914:dest1 2915echo goto with no leading space worked 2916if a==a goto :dest1b 2917echo FAILURE at dest 1b 2918:dest1b 2919echo goto with colon and no leading space worked 2920if b==b goto dest2 2921echo FAILURE at dest 2 2922 :dest2 2923echo goto with a leading space worked 2924if c==c goto dest3 2925echo FAILURE at dest 3 2926 :dest3 2927echo goto with a leading tab worked 2928if d==d goto dest4 2929echo FAILURE at dest 4 2930:dest4@space@ 2931echo goto with a following space worked 2932if e==e goto dest5 2933echo FAILURE at dest 5 2934:dest5&& echo FAILURE 2935echo goto with following amphersands worked 2936 2937del failure.txt >nul 2>&1 2938if f==f goto dest6 2939echo FAILURE at dest 6 2940:dest6>FAILURE.TXT 2941if exist FAILURE.TXT echo FAILURE at dest 6 as file exists 2942echo goto with redirections worked 2943del FAILURE.TXT >nul 2>&1 2944 2945:: some text that is ignored | dir >cmd_output | another test 2946if exist cmd_output echo FAILURE at dest 6 as file exists 2947echo Ignoring double colons worked 2948del cmd_output >nul 2>&1 2949 2950rem goto a label which does not exist issues an error message and 2951rem acts the same as goto :EOF, and ensure ::label is never matched 2952del testgoto.bat >nul 2>&1 2953echo goto :dest7 ^>nul 2^>^&1 >> testgoto.bat 2954echo echo FAILURE at dest 7 - Should have not found label and issued an error plus ended the batch>> testgoto.bat 2955echo ::dest7>> testgoto.bat 2956echo echo FAILURE at dest 7 - Incorrectly went to label >> testgoto.bat 2957call testgoto.bat 2958del testgoto.bat >nul 2>&1 2959 2960del testgoto.bat >nul 2>&1 2961echo goto ::dest8 ^>nul 2^>^&1 >> testgoto.bat 2962echo echo FAILURE at dest 8 - Should have not found label and issued an error plus ended the batch>> testgoto.bat 2963echo ::dest8>> testgoto.bat 2964echo echo FAILURE at dest 8 - Incorrectly went to label >> testgoto.bat 2965call testgoto.bat 2966del testgoto.bat >nul 2>&1 2967 2968if g==g goto dest9 2969echo FAILURE at dest 9 2970:dest91 2971echo FAILURE at dest 91 2972@ : dest9>rubbish 2973echo label with mixed whitespace and no echo worked 2974 2975if h==h goto :dest10:this is ignored 2976echo FAILURE at dest 10 2977:dest10:this is also ignored 2978echo Correctly ignored trailing information 2979 2980echo ------------ Testing PATH ------------ 2981set WINE_backup_path=%path% 2982set path=original 2983path 2984path try2 2985path 2986path=try3 2987path 2988set path=%WINE_backup_path% 2989set WINE_backup_path= 2990 2991echo ------------ Testing combined CALLs/GOTOs ------------ 2992echo @echo off>foo.cmd 2993echo goto :eof>>foot.cmd 2994echo :eof>>foot.cmd 2995echo echo world>>foo.cmd 2996 2997echo @echo off>foot.cmd 2998echo echo cheball>>foot.cmd 2999echo.>>foot.cmd 3000echo call :bar>>foot.cmd 3001echo if "%%1"=="deleteMe" (del foot.cmd)>>foot.cmd 3002echo goto :eof>>foot.cmd 3003echo.>>foot.cmd 3004echo :bar>>foot.cmd 3005echo echo barbare>>foot.cmd 3006echo goto :eof>>foot.cmd 3007 3008call foo.cmd 3009call foot 3010call :bar 3011del foo.cmd 3012rem Script execution stops after the following line 3013foot deleteMe 3014call :foo 3015call :foot 3016goto :endFuns 3017 3018:foot 3019echo foot 3020 3021:foo 3022echo foo 3023goto :eof 3024 3025:endFuns 3026 3027:bar 3028echo bar 3029call :foo 3030 3031:baz 3032echo baz 3033goto :eof 3034 3035echo Final message is not output since earlier 'foot' processing stops script execution 3036echo Do NOT add any tests below this line 3037 3038echo ------------ Done, jumping to EOF ----------- 3039goto :eof 3040rem Subroutine to set errorlevel and return 3041rem in windows nt 4.0, this always sets errorlevel 1, since /b isn't supported 3042:setError 3043exit /B %1 3044rem This line runs under cmd in windows NT 4, but not in more modern versions. 3045