1 echo Tests for cmd's builtin commands
4 echo ------------ Testing 'echo' [ON] ------------
6 echo 'singlequotedword'
7 echo "doublequotedword"
20 echo word@space@@space@
24 echo@tab@word@tab@@space@
36 echo ------------ Testing 'echo' [OFF] ------------
38 echo 'singlequotedword'
39 echo "doublequotedword"
52 echo word@space@@space@
56 echo@tab@word@tab@@space@
62 echo ------------ Testing mixed echo modes ------------
63 echo @echo on> mixedEchoModes.cmd
64 echo if 1==1 echo foo>> mixedEchoModes.cmd
65 echo if 1==1 @echo bar>> mixedEchoModes.cmd
66 echo @echo off>> mixedEchoModes.cmd
67 echo if 1==1 echo foo2>> mixedEchoModes.cmd
68 echo if 1==1 @echo bar2>> mixedEchoModes.cmd
69 type mixedEchoModes.cmd
70 cmd /c mixedEchoModes.cmd
71 del mixedEchoModes.cmd
73 echo ------------ Testing parameterization ------------
75 call :TestParm "a b c"
76 call :TestParm "a b"\c
77 call :TestParm a=~`+,.{}!+b
81 call :TestParm a[b]{c}(d)e
82 call :TestParm a&echo second line
83 call :TestParm a b,,,c
84 call :TestParm a==b;;c
93 echo ------------ Testing rem ------------
98 rem echo foo & echo bar
101 rem@tab@echo foo & echo bar
107 rem echo foo & echo bar
110 rem@tab@echo foo & echo bar
113 echo ------------ Testing redirection operators ------------
114 mkdir foobar & cd foobar
115 echo --- stdout redirection
124 echo foo@tab@1>@tab@foo
145 echo --- stdout appending
163 echo foo7 7>> foo || (echo not supported & del foo)
164 if exist foo (type foo) else echo not supported
165 echo --- redirections within IF statements
166 if 1==1 echo foo1>bar
169 if 1==1 (echo foo2>bar) else echo baz2>bar
171 if 1==1 (echo foo3) else echo baz3>bar
172 type bar || echo file does not exist, ok
173 if 1==1 (echo foo4>bar) else echo baz4>bar
175 if 1==0 (echo foo5>bar) else echo baz5>bar
177 if 1==0 (echo foo6) else echo baz6 1>bar
179 if 1==0 (echo foo7 1>bar) else echo baz7>bar
181 if 1==0 (echo foo8 1>bar) else echo baz8>bak
183 if 1==1 (echo foo>bar & echo baz)
190 (if 1==1 (echo A) else echo B) > C
192 (if 1==0 (echo A) else echo B) > C
194 (if 1==0 (echo A > B) else echo C)
195 cd .. & rd /s/q foobar
197 echo ------------ Testing circumflex escape character ------------
198 rem 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
220 echo bak ^&& echo baz 2> nul
230 rem FIXME: echoing %FOO% gives an error (baz not recognized) but prematurely
231 rem exits the script on windows; redirecting stdout and/or stderr doesn't help
240 echo ------------ Testing 'set' ------------
242 set FOOBAR 2> nul > nul
246 echo %FOOBAR%FOOBAR not defined
258 echo %FOOBAR%FOOBAR not defined
260 set FOOBA 2> nul > nul
270 echo %FOO%FOO not defined
275 echo set "FOO=bar" should not include the quotes in the variable value
288 echo ------------ Testing variable expansion ------------
290 echo ~dp0 should be directory containing batch file
306 echo %ERRORLEVEL%%ERRORLEVEL%
307 echo %ERRORLEVEL%ERRORLEVEL%
314 echo ------------ Testing variable substrings ------------
327 echo ------------ Testing variable substitution ------------
328 echo --- in FOR variables
329 for %%i in ("A B" C) do echo %%i
330 rem check works when prefix with @
331 @for %%i in ("A B" C) do echo %%i
333 for %%i in ("A B" C) do echo '%%~i'
334 rem fully qualified path
335 for %%f in ("C D" E) do echo %%~ff
337 for %%i in ("F G" H) do echo %%~di
339 for %%d in ("I J" K) do echo %%~pd
341 for %%i in ("L M" N) do echo %%~ni
343 for %%i in ("O. P.OOL" Q.TABC hello) do echo '%%~xi'
344 rem path with short path names
345 for %%I in ("R S" T ABCDEFGHIJK.LMNOP) do echo '%%~sI'
347 for %%i in ("U V" W) do echo '%%~ai'
349 for %%i in (foo) do echo '%%~ai'
350 for %%i in (foo) do echo '%%~zi'
353 rem Not fully testable, until we can grep dir's output to get foo's creation time in an envvar...
354 for %%i in ("a b" c) do echo '%%~ti'
356 rem Similar issues as above
357 for %%i in ("a b" c) do echo '%%~zi'
359 for %%i in ("d e" f) do echo %%~dpi
360 for %%i in ("g h" i) do echo %%~sdi
361 for %%i in ("g h" i) do echo %%~dsi
362 for %%i in ("j k" l.eh) do echo '%%~xsi'
364 echo --- in parameters
365 for %%i in ("A B" C) do call :echoFun %%i
367 for %%i in ("A B" C) do call :echoFunQ %%i
368 rem fully qualified path
369 for %%f in ("C D" E) do call :echoFunF %%f
371 for %%i in ("F G" H) do call :echoFunD %%i
373 for %%d in ("I J" K) do call :echoFunP %%d
375 for %%i in ("L M" N) do call :echoFunN %%i
377 for %%i in ("O. P.OOL" Q.TABC hello) do call :echoFunX %%i
378 rem path with short path names
379 for %%I in ("R S" T ABCDEFGHIJK.LMNOP) do call :echoFunS %%I
380 rem NT4 aborts whole script execution when encountering ~a, ~t and ~z substitutions, preventing full testing
382 for %%i in ("d e" f) do call :echoFunDP %%i
383 for %%i in ("g h" i) do call :echoFunSD %%i
384 for %%i in ("g h" i) do call :echoFunDS %%i
385 for %%i in ("j k" l.eh) do call :echoFunXS %%i
417 rem some NT4 workaround
440 echo ------------ Testing variable delayed expansion ------------
441 rem NT4 doesn't support this
442 echo --- default mode (load-time expansion)
448 if %FOO% == bar (echo bar) else echo foo
454 if !FOO! == bar (echo bar) else echo foo
457 echo --- runtime (delayed) expansion mode
458 setlocal EnableDelayedExpansion
464 if %FOO% == bar (echo bar) else echo foo
470 if !FOO! == bar (echo bar) else echo foo
473 setlocal DisableDelayedExpansion
479 echo --- using /V cmd flag
480 echo @echo off> tmp.cmd
481 echo set FOO=foo>> tmp.cmd
482 echo echo %%FOO%%>> tmp.cmd
483 echo echo !FOO!>> tmp.cmd
484 echo set FOO=>> tmp.cmd
486 cmd /V:OfF /C tmp.cmd
489 echo ------------ Testing conditional execution ------------
490 echo --- unconditional ampersand
491 call :setError 123 & echo foo1
492 echo bar2 & echo foo2
493 mkdir foobar & cd foobar
495 cd .. & rd /s/q foobar
497 echo foobar not deleted!
500 ) else echo foobar deleted
501 echo --- on success conditional and
502 call :setError 456 && echo foo3 > foo3
506 ) else echo foo3 not created
507 echo bar4 && echo foo4
508 echo --- on failure conditional or
509 call :setError 789 || echo foo5
510 echo foo6 || echo bar6 > bar6
516 echo ------------ Testing cd ------------
519 echo blabla > singleFile
521 echo Current dir: %CD%
536 if not exist foobar (cd ..)
538 cd@tab@..@tab@@space@@tab@
540 if not exist foobar (cd ..)
554 cd "bar bak@space@"@tab@@space@
565 echo ------------ Testing type ------------
579 echo ------------ Testing NUL ------------
580 md foobar & cd foobar
581 rem NUL file (non) creation + case insensitivity
582 rem Note: "if exist" does not work with NUL, so to check for file existence we use a kludgy workaround
591 rem NUL not special everywhere
594 if not exist foo (echo foo should have been created) else (
598 rem Empty file creation
609 echo ------------ Testing if/else ------------
610 echo --- if/else should work with blocks
612 echo if seems to work
614 echo if seems to be broken
617 echo else seems to be broken
619 echo else seems to work
622 echo if seems not to detect /c as parameter
624 echo parameter detection seems to be broken
627 echo --- case sensitivity with and without /i option
628 if bar==BAR echo if does not default to case sensitivity
629 if not bar==BAR echo if seems to default to case sensitivity
630 if /i foo==FOO echo if /i seems to work
631 if /i not foo==FOO echo if /i seems to be broken
632 if /I foo==FOO echo if /I seems to work
633 if /I not foo==FOO echo if /I seems to be broken
635 echo --- string comparisons
636 if abc == abc (echo equal) else echo non equal
637 if abc =="abc" (echo equal) else echo non equal
638 if "abc"== abc (echo equal) else echo non equal
639 if "abc"== "abc" (echo equal) else echo non equal
641 echo --- tabs handling
642 if@tab@1==1 echo doom
643 if @tab@1==1 echo doom
644 if 1==1 (echo doom) else@tab@echo quake
645 if@tab@not @tab@1==@tab@0 @tab@echo lol
646 if 1==0@tab@(echo doom) else echo quake
647 if 1==0 (echo doom)@tab@else echo quake
648 if 1==0 (echo doom) else@tab@echo quake
650 echo --- comparison operators
651 rem NT4 misevaluates conditionals in for loops so we have to use subroutines as workarounds
652 echo ------ for strings
653 rem NT4 stops processing of the whole batch file as soon as it finds a
654 rem comparison operator non fully uppercased, such as lss instead of LSS, so we
655 rem can't test those here.
656 if LSS LSS LSSfoo (echo LSS string can be used as operand for LSS comparison)
657 if LSS LSS LSS (echo bar)
658 if 1.1 LSS 1.10 (echo floats are handled as strings)
659 if "9" LSS "10" (echo numbers in quotes recognized!) else echo numbers in quotes are handled as strings
660 if not "-1" LSS "1" (echo negative numbers as well) else echo NT4
661 if /i foo LSS FoOc echo if /i seems to work for LSS
662 if /I not foo LSS FOOb echo if /I seems to be broken for LSS
663 set STR_PARMS=A B AB BA AA
664 for %%i in (%STR_PARMS%) do (
665 for %%j in (%STR_PARMS%) do (
666 call :LSStest %%i %%j))
667 if b LSS B (echo b LSS B) else echo NT4
668 if /I b LSS B echo b LSS B insensitive
669 if b LSS A echo b LSS A
670 if /I b LSS A echo b LSS A insensitive
671 if a LSS B (echo a LSS B) else echo NT4
672 if /I a LSS B echo a LSS B insensitive
673 if A LSS b echo A LSS b
674 if /I A LSS b echo A LSS b insensitive
675 for %%i in (%STR_PARMS%) do (
676 for %%j in (%STR_PARMS%) do (
677 call :LEQtest %%i %%j))
678 if b LEQ B (echo b LEQ B) else echo NT4
679 if /I b LEQ B echo b LEQ B insensitive
680 if b LEQ A echo b LEQ A
681 if /I b LEQ A echo b LEQ A insensitive
682 if a LEQ B (echo a LEQ B) else echo NT4
683 if /I a LEQ B echo a LEQ B insensitive
684 if A LEQ b echo A LEQ b
685 if /I A LEQ b echo A LEQ b insensitive
686 for %%i in (%STR_PARMS%) do (
687 for %%j in (%STR_PARMS%) do (
688 call :EQUtest %%i %%j))
689 if /I A EQU a echo A EQU a insensitive
690 for %%i in (%STR_PARMS%) do (
691 for %%j in (%STR_PARMS%) do (
692 call :NEQtest %%i %%j))
693 for %%i in (%STR_PARMS%) do (
694 for %%j in (%STR_PARMS%) do (
695 call :GEQtest %%i %%j))
696 for %%i in (%STR_PARMS%) do (
697 for %%j in (%STR_PARMS%) do (
698 call :GTRtest %%i %%j))
699 echo ------ for numbers
700 if -1 LSS 1 (echo negative numbers handled)
701 if not -1 LSS -10 (echo negative numbers handled)
702 if not 9 LSS 010 (echo octal handled)
703 if not -010 LSS -8 (echo also in negative form)
704 if 4 LSS 0x5 (echo hexa handled)
705 if not -1 LSS -0x1A (echo also in negative form)
706 if 11 LSS 101 (echo 11 LSS 101)
707 set INT_PARMS=0 1 10 9
708 for %%i in (%INT_PARMS%) do (
709 for %%j in (%INT_PARMS%) do (
710 call :LSStest %%i %%j))
711 for %%i in (%INT_PARMS%) do (
712 for %%j in (%INT_PARMS%) do (
713 call :LEQtest %%i %%j))
714 for %%i in (%INT_PARMS%) do (
715 for %%j in (%INT_PARMS%) do (
716 call :EQUtest %%i %%j))
717 if 011 EQU 9 (echo octal ok)
718 if 0xA1 EQU 161 (echo hexa ok)
719 if 0xA1 EQU "161" (echo hexa should be recognized) else (echo string/hexa compare ok)
720 if "0xA1" EQU 161 (echo hexa should be recognized) else (echo string/hexa compare ok)
721 for %%i in (%INT_PARMS%) do (
722 for %%j in (%INT_PARMS%) do (
723 call :NEQtest %%i %%j))
724 for %%i in (%INT_PARMS%) do (
725 for %%j in (%INT_PARMS%) do (
726 call :GEQtest %%i %%j))
727 for %%i in (%INT_PARMS%) do (
728 for %%j in (%INT_PARMS%) do (
729 call :GTRtest %%i %%j))
730 echo ------ for numbers and stringified numbers
731 if not "1" EQU 1 (echo strings and integers not equal) else echo foo
732 if not 1 EQU "1" (echo strings and integers not equal) else echo foo
733 if '1' EQU 1 echo '1' EQU 1
734 if 1 EQU '1' echo 1 EQU '1'
735 if not "1" GEQ 1 (echo foo) else echo bar
736 if "10" GEQ "1" echo "10" GEQ "1"
737 if '1' GEQ 1 (echo '1' GEQ 1) else echo NT4
738 if 1 GEQ "1" echo 1 GEQ "1"
739 if "1" GEQ "1" echo "1" GEQ "1"
740 if '1' GEQ "1" echo '1' GEQ "1"
741 if "10" GEQ "1" echo "10" GEQ "1"
742 if not 1 GEQ '1' (echo non NT4) else echo 1 GEQ '1'
743 for %%i in ("1" '1') do call :GEQtest %%i '1'
744 if "10" GEQ '1' (echo "10" GEQ '1') else echo foo
745 if 1 GEQ "10" (echo 1 GEQ "10") else echo foo
746 if "1" GEQ "10" (echo 1 GEQ "10") else echo foo
747 if '1' GEQ "10" (echo '1' GEQ "10") else echo foo
748 if "10" GEQ "10" (echo "10" GEQ "10")
749 goto :endIfCompOpsSubroutines
751 rem IF subroutines helpers
753 if %1 LSS %2 echo %1 LSS %2
756 if %1 LEQ %2 echo %1 LEQ %2
759 if %1 EQU %2 echo %1 EQU %2
762 if %1 NEQ %2 echo %1 NEQ %2
765 if %1 GEQ %2 echo %1 GEQ %2
768 if %1 GTR %2 echo %1 GTR %2
771 :endIfCompOpsSubroutines
775 echo ------------ Testing for ------------
777 for %%i in (A B C) do echo %%i
778 for %%i in (A B C) do echo %%I
779 for %%i in (A B C) do echo %%j
780 for %%i in (A B C) do call :forTestFun1 %%i
781 for %%i in (1,4,1) do echo %%i
782 for %%i in (A, B,C) do echo %%i
783 for %%i in (X) do echo %%i
784 for@tab@%%i in (X2) do echo %%i
785 for %%i in@tab@(X3) do echo %%i
786 for %%i in (@tab@ foo@tab@) do echo %%i
787 for@tab@ %%i in@tab@(@tab@M) do echo %%i
788 for %%i@tab@in (X)@tab@do@tab@echo %%i
789 for@tab@ %%j in@tab@(@tab@M, N, O@tab@) do echo %%j
790 for %%i in (`echo A B`) do echo %%i
791 for %%i in ('echo A B') do echo %%i
792 for %%i in ("echo A B") do echo %%i
793 for %%i in ("A B" C) do echo %%i
799 echo --- imbricated FORs
806 for %%i in (A B) do (
807 for %%j in (C D) do (
809 for %%i in (A B) do (
810 for %%j in (C D) do (
811 call :forTestFun2 %%i %%j ))
817 mkdir foobar & cd foobar
822 echo --- basic wildcards
823 for %%i in (ba*) do echo %%i
825 for /d %%i in (baz foo bar) do echo %%i 2>&1
826 rem Confirm we don't match files:
827 for /d %%i in (bazb*) do echo %%i 2>&1
828 for /d %%i in (bazb2*) do echo %%i 2>&1
829 rem Show we pass through non wildcards
830 for /d %%i in (PASSED) do echo %%i
831 for /d %%i in (xxx) do (
832 echo %%i - Should be xxx
833 echo Expected second line
835 rem Show we issue no messages on failures
836 for /d %%i in (FAILED?) do echo %%i 2>&1
837 for /d %%i in (FAILED?) do (
838 echo %%i - Unexpected!
839 echo FAILED Unexpected second line
841 for /d %%i in (FAILED*) do echo %%i 2>&1
842 for /d %%i in (FAILED*) do (
843 echo %%i - Unexpected!
844 echo FAILED Unexpected second line
846 rem FIXME can't test wildcard expansion here since it's listed in directory
847 rem order, and not in alphabetic order.
848 rem Proper testing would need a currently missing "sort" program implementation.
849 rem for /d %%i in (ba*) do echo %%i>> tmp
852 rem for /d %%i in (?a*) do echo %%i>> tmp
855 rem for /d %%i in (*) do echo %%i>> tmp
863 call :WriteLine set found=N
864 for /l %%i in (1,1,%expectedresults%) do (
865 call :WriteLine if "%%%%expectedresults.%%i%%%%"=="%%%%1" set found=Y
866 call :WriteLine if "%%%%found%%%%"=="Y" set expectedresults.%%i=
867 call :WriteLine if "%%%%found%%%%"=="Y" goto :eof
869 call :WriteLine echo Got unexpected result: "%%%%1"
878 for /l %%i in (1,1,%expectedresults%) do call :WriteLine if not "%%%%expectedresults.%%i%%%%"=="" echo Found missing result: "%%%%expectedresults.%%i%%%%"
884 rem %CD% does not tork on NT4 so use the following workaround
885 for /d %%i in (.) do set CURDIR=%%~dpnxi
888 echo Plain directory enumeration
889 set expectedresults=4
890 set expectedresults.1=%CURDIR%\.
891 set expectedresults.2=%CURDIR%\bar\.
892 set expectedresults.3=%CURDIR%\baz\.
893 set expectedresults.4=%CURDIR%\foo\.
895 for /R %%i in (.) do call temp.bat %%i
896 call :ValidateExpected
898 echo Plain directory enumeration from provided root
899 set expectedresults=4
900 set expectedresults.1=%CURDIR%\.
901 set expectedresults.2=%CURDIR%\bar\.
902 set expectedresults.3=%CURDIR%\baz\.
903 set expectedresults.4=%CURDIR%\foo\.
904 if "%CD%"=="" goto :SkipBrokenNT4
906 for /R "%CURDIR%" %%i in (.) do call temp.bat %%i
907 call :ValidateExpected
910 echo File enumeration
911 set expectedresults=2
912 set expectedresults.1=%CURDIR%\baz\bazbaz
913 set expectedresults.2=%CURDIR%\bazbaz
915 for /R %%i in (baz*) do call temp.bat %%i
916 call :ValidateExpected
918 echo File enumeration from provided root
919 set expectedresults=2
920 set expectedresults.1=%CURDIR%\baz\bazbaz
921 set expectedresults.2=%CURDIR%\bazbaz
923 for /R %%i in (baz*) do call temp.bat %%i
924 call :ValidateExpected
926 echo Mixed enumeration
927 set expectedresults=6
928 set expectedresults.1=%CURDIR%\.
929 set expectedresults.2=%CURDIR%\bar\.
930 set expectedresults.3=%CURDIR%\baz\.
931 set expectedresults.4=%CURDIR%\baz\bazbaz
932 set expectedresults.5=%CURDIR%\bazbaz
933 set expectedresults.6=%CURDIR%\foo\.
935 for /R %%i in (. baz*) do call temp.bat %%i
936 call :ValidateExpected
938 echo Mixed enumeration from provided root
939 set expectedresults=6
940 set expectedresults.1=%CURDIR%\.
941 set expectedresults.2=%CURDIR%\bar\.
942 set expectedresults.3=%CURDIR%\baz\.
943 set expectedresults.4=%CURDIR%\baz\bazbaz
944 set expectedresults.5=%CURDIR%\bazbaz
945 set expectedresults.6=%CURDIR%\foo\.
947 for /R %%i in (. baz*) do call temp.bat %%i
948 call :ValidateExpected
950 echo With duplicates enumeration
951 set expectedresults=12
952 set expectedresults.1=%CURDIR%\bar\bazbaz
953 set expectedresults.2=%CURDIR%\bar\fred
954 set expectedresults.3=%CURDIR%\baz\bazbaz
955 set expectedresults.4=%CURDIR%\baz\bazbaz
956 set expectedresults.5=%CURDIR%\baz\bazbaz
957 set expectedresults.6=%CURDIR%\baz\fred
958 set expectedresults.7=%CURDIR%\bazbaz
959 set expectedresults.8=%CURDIR%\bazbaz
960 set expectedresults.9=%CURDIR%\bazbaz
961 set expectedresults.10=%CURDIR%\foo\bazbaz
962 set expectedresults.11=%CURDIR%\foo\fred
963 set expectedresults.12=%CURDIR%\fred
965 for /R %%i in (baz* bazbaz fred ba*) do call temp.bat %%i
966 call :ValidateExpected
968 echo Strip missing wildcards, keep unwildcarded names
969 set expectedresults=6
970 set expectedresults.1=%CURDIR%\bar\jim
971 set expectedresults.2=%CURDIR%\baz\bazbaz
972 set expectedresults.3=%CURDIR%\baz\jim
973 set expectedresults.4=%CURDIR%\bazbaz
974 set expectedresults.5=%CURDIR%\foo\jim
975 set expectedresults.6=%CURDIR%\jim
977 for /R %%i in (baz* fred* jim) do call temp.bat %%i
978 call :ValidateExpected
981 cd .. & rd /s/Q foobar
983 rem 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
984 for /L %%i in (1,2,0) do echo %%i
985 for@tab@/L %%i in (1,2,0) do echo %%i
986 for /L %%i in (1,2,6) do echo %%i
987 for /l %%i in (1 ,2,6) do echo %%i
988 for /L %%i in (a,2,3) do echo %%i
989 for /L %%i in (1,2,-1) do echo %%i
990 for /L %%i in (-4,-1,-1) do echo %%i
991 for /L %%i in (1,-2,-2) do echo %%i
992 for /L %%i in (1,2,a) do echo %%i
993 echo ErrorLevel %ErrorLevel%
994 for /L %%i in (1,a,b) do echo %%i
995 echo ErrorLevel %ErrorLevel%
997 for /l %%i in (1,1,4) do echo %%i
998 for /l %%i in (1,2,4) do echo %%i
999 for /l %%i in (4,-1,1) do echo %%i
1000 for /l %%i in (4,-2,1) do echo %%i
1001 for /l %%i in (1,-1,4) do echo %%i
1002 for /l %%i in (4,1,1) do echo %%i
1003 for /L %%i in (a,2,b) do echo %%i
1004 for /L %%i in (1,1,1) do echo %%i
1005 for /L %%i in (1,-2,-1) do echo %%i
1006 for /L %%i in (-1,-1,-1) do echo %%i
1007 for /L %%i in (1,2, 3) do echo %%i
1008 rem Test zero iteration skips the body of the for
1009 for /L %%i in (2,2,1) do (
1014 rem No output when using "set expr" syntax, unless in interactive mode
1015 rem Need to use "set envvar=expr" to use in a batch script
1016 echo ------ individual operations
1018 set /a var=1 +2 & echo %var%
1019 set /a var=1 +-2 & echo %var%
1020 set /a var=1 --2 & echo %var%
1021 set /a var=2* 3 & echo %var%
1022 set /a var=-2* -5 & echo %var%
1023 set /a var=12/3 & echo %var%
1024 set /a var=13/3 & echo %var%
1025 set /a var=-13/3 & echo %var%
1026 rem FIXME Divide by zero should return an error, but error messages cannot be tested with current infrastructure
1027 set /a var=5 %% 5 & echo %var%
1028 set /a var=5 %% 3 & echo %var%
1029 set /a var=5 %% -3 & echo %var%
1030 set /a var=-5 %% -3 & echo %var%
1031 set /a var=1 ^<^< 0 & echo %var%
1032 set /a var=1 ^<^< 2 & echo %var%
1033 set /a var=1 ^<^< -2 & echo %var%
1034 set /a var=-1 ^<^< -2 & echo %var%
1035 set /a var=-1 ^<^< 2 & echo %var%
1036 set /a var=9 ^>^> 0 & echo %var%
1037 set /a var=9 ^>^> 2 & echo %var%
1038 set /a var=9 ^>^> -2 & echo %var%
1039 set /a var=-9 ^>^> -2 & echo %var%
1040 set /a var=-9 ^>^> 2 & echo %var%
1041 set /a var=5 ^& 0 & echo %var%
1042 set /a var=5 ^& 1 & echo %var%
1043 set /a var=5 ^& 3 & echo %var%
1044 set /a var=5 ^& 4 & echo %var%
1045 set /a var=5 ^& 1 & echo %var%
1046 set /a var=5 ^| 0 & echo %var%
1047 set /a var=5 ^| 1 & echo %var%
1048 set /a var=5 ^| 3 & echo %var%
1049 set /a var=5 ^| 4 & echo %var%
1050 set /a var=5 ^| 1 & echo %var%
1051 set /a var=5 ^^ 0 & echo %var%
1052 set /a var=5 ^^ 1 & echo %var%
1053 set /a var=5 ^^ 3 & echo %var%
1054 set /a var=5 ^^ 4 & echo %var%
1055 set /a var=5 ^^ 1 & echo %var%
1056 echo ------ precedence and grouping
1057 set /a var=4 + 2*3 & echo %var%
1058 set /a var=(4+2)*3 & echo %var%
1059 set /a var=4 * 3/5 & echo %var%
1060 set /a var=(4 * 3)/5 & echo %var%
1061 set /a var=4 * 5 %% 4 & echo %var%
1062 set /a var=4 * (5 %% 4) & echo %var%
1063 set /a var=3 %% (5 + 8 %% 3 ^^ 2) & echo %var%
1064 set /a var=3 %% (5 + 8 %% 3 ^^ -2) & echo %var%
1065 echo ------ octal and hexadecimal
1066 set /a var=0xf + 3 & echo %var%
1067 set /a var=0xF + 3 & echo %var%
1068 set /a var=015 + 2 & echo %var%
1069 set /a var=3, 8+3,0 & echo %var%
1070 echo ------ variables
1071 set /a var=foo=3, foo+1 & echo %var%
1072 if defined foo (echo %foo%) else (
1073 echo foo not defined
1075 set /a var=foo=3, foo+=1 & echo %var%
1076 set /a var=foo=3, bar=1, bar+=foo, bar & echo %var%
1077 set /a var=foo*= foo & echo %var%
1078 set /a var=whateverNonExistingVar & echo %var%
1079 set /a var=whateverNonExistingVar + bar & echo %var%
1080 set /a var=foo -= foo + 7 & echo %var%
1081 set /a var=foo /= 3 + 2 & echo %var%
1082 set /a var=foo=5, foo %%=2 & echo %var%
1083 set /a var=foo ^<^<= 2 & echo %var%
1084 set /a var=foo ^>^>= 2 & echo %var%
1085 set /a var=foo ^&= 2 & echo %var%
1086 set /a var=foo=5, foo ^|= 2 & echo %var%
1087 set /a var=foo=5, foo ^^= 2 & echo %var%
1088 set /a var=foo=19, foo %%= 4 + (bar %%= 7) & echo.
1093 mkdir foobar & cd foobar
1094 echo ------ string argument
1095 rem NT4 does not support usebackq
1096 for /F %%i in ("a b c") do echo %%i
1097 for /f usebackq %%i in ('a b c') do echo %%i>output_file
1098 if not exist output_file (echo no output) else (type output_file & del output_file)
1099 for /f %%i in ("a ") do echo %%i
1100 for /f usebackq %%i in ('a ') do echo %%i>output_file
1101 if not exist output_file (echo no output) else (type output_file & del output_file)
1102 for /f %%i in ("a") do echo %%i
1103 for /f usebackq %%i in ('a') do echo %%i>output_file
1104 if not exist output_file (echo no output) else (type output_file & del output_file)
1105 fOr /f %%i in (" a") do echo %%i
1106 for /f usebackq %%i in (' a') do echo %%i>output_file
1107 if not exist output_file (echo no output) else (type output_file & del output_file)
1108 for /f %%i in (" a ") do echo %%i
1109 for /f usebackq %%i in (' a ') do echo %%i>output_file
1110 if not exist output_file (echo no output) else (type output_file & del output_file)
1111 echo ------ fileset argument
1112 echo --------- basic blank handling
1114 for /f %%i in (foo) do echo %%i
1116 for /f %%i in (foo) do echo %%i
1118 for /f %%i in (foo) do echo %%i
1120 for /f %%i in (foo) do echo %%i
1122 for /f %%i in (foo) do echo %%i
1124 for /f %%i in (foo) do echo %%i
1127 for /f %%i in (foo) do echo %%i
1128 echo --------- multi-line with empty lines
1135 for /f %%b in (foo) do echo %%b
1136 echo --------- multiple files
1140 for /f %%k in (foo bar) do echo %%k
1141 for /f %%k in (bar foo) do echo %%k
1142 echo ------ command argument
1143 rem Not implemented on NT4, need to skip it as no way to get output otherwise
1144 if "%CD%"=="" goto :SkipFORFcmdNT4
1145 for /f %%i in ('echo.Passed1') do echo %%i
1146 for /f "usebackq" %%i in (`echo.Passed2`) do echo %%i
1147 for /f usebackq %%i in (`echo.Passed3`) do echo %%i
1150 for /l %%i in (1,1,3) do echo Missing functionality - Broken%%i
1152 rem FIXME: Rest not testable right now in wine: not implemented and would need
1153 rem preliminary grep-like program implementation (e.g. like findstr or fc) even
1154 rem for a simple todo_wine test
1155 rem (for /f "usebackq" %%i in (`echo z a b`) do echo %%i) || echo not supported
1156 rem (for /f usebackq %%i in (`echo z a b`) do echo %%i) || echo not supported
1157 echo ------ eol option
1158 if "%CD%"=="" goto :SkipFORFeolNT4
1160 echo and Line two>>foo
1161 echo Line three>>foo
1162 for /f "eol=L" %%i in (foo) do echo %%i
1163 for /f "eol=a" %%i in (foo) do echo %%i
1165 goto :ContinueFORFeol
1167 for /l %%i in (1,1,3) do echo Broken NT4 functionality%%i
1169 for /f "eol=@" %%i in (" ad") do echo %%i
1170 for /f "eol=@" %%i in (" z@y") do echo %%i
1171 for /f "eol=|" %%i in ("a|d") do echo %%i
1172 for /f "eol=@" %%i in ("@y") do echo %%i > output_file
1173 if not exist output_file (echo no output) else (del output_file)
1174 for /f "eol==" %%i in ("=y") do echo %%i > output_file
1175 if not exist output_file (echo no output) else (del output_file)
1176 echo ------ delims option
1177 for /f "delims=|" %%i in ("a|d") do echo %%i
1178 for /f "delims=|" %%i in ("a |d") do echo %%i
1179 for /f "delims=|" %%i in ("a d|") do echo %%i
1180 for /f "delims=| " %%i in ("a d|") do echo %%i
1181 for /f "delims==" %%i in ("C r=d|") do echo %%i
1182 for /f "delims=" %%i in ("foo bar baz") do echo %%i
1183 for /f "delims=" %%i in ("c:\foo bar baz\..") do echo %%~fi
1184 echo ------ skip option
1188 for /f "skip=2" %%i in (foo) do echo %%i
1189 for /f "skip=3" %%i in (foo) do echo %%i > output_file
1190 if not exist output_file (echo no output) else (del output_file)
1191 for /f "skip=4" %%i in (foo) do echo %%i > output_file
1192 if not exist output_file (echo no output) else (del output_file)
1193 for /f "skip=02" %%i in (foo) do echo %%i
1194 for /f "skip=0x2" %%i in (foo) do echo %%i
1195 for /f "skip=1" %%i in ("skipme") do echo %%i > output_file
1196 if not exist output_file (echo no output) else (del output_file)
1200 echo ------------ Testing del /a ------------
1201 del /f/q *.test > nul
1204 echo not-r > not-r.test
1206 if not exist not-r.test echo not-r.test not found before delete, bad
1208 if not exist not-r.test echo not-r.test not found after delete, good
1210 if not exist r.test echo r.test not found before delete, bad
1211 if exist r.test echo r.test found before delete, good
1213 if not exist r.test echo r.test not found after delete, good
1214 if exist r.test echo r.test found after delete, bad
1216 echo ------------ Testing del /q ------------
1220 echo abc > file2.dat
1221 rem If /q doesn't work, cmd will prompt and the test case should hang
1223 for %%a in (1 2.dat) do if exist file%%a echo del /q * failed on file%%a
1224 for %%a in (1 2.dat) do if not exist file%%a echo del /q * succeeded on file%%a
1228 echo ------------ Testing del /s ------------
1233 echo there > file2.dat
1234 echo bub > file3.dat
1235 echo bye > "file with spaces.dat"
1237 del /s file1.dat > nul
1238 del file2.dat /s > nul
1239 del "file3.dat" /s > nul
1240 del "file with spaces.dat" /s > nul
1242 for %%f in (1 2 3) do if exist file%%f.dat echo Del /s failed on file%%f
1243 for %%f in (1 2 3) do if exist file%%f.dat del file%%f.dat
1244 if exist "file with spaces.dat" echo Del /s failed on "file with spaces.dat"
1245 if exist "file with spaces.dat" del "file with spaces.dat"
1250 echo ------------ Testing rename ------------
1251 mkdir foobar & cd foobar
1252 echo --- ren and rename are synonymous
1255 if exist foo echo foo should be renamed!
1256 if exist bar echo foo renamed to bar
1258 if exist bar echo bar should be renamed!
1259 if exist foo echo bar renamed to foo
1260 echo --- name collision
1270 echo --- rename read-only files
1274 if not exist file1 (
1276 echo read-only file renamed
1279 echo read-only file not renamed!
1281 echo --- rename directories
1293 echo read-only dir renamed
1296 echo --- rename in other directory
1297 if not exist baz\abc (
1298 echo rename impossible in other directory
1299 if exist foo echo original file still present
1301 echo shouldn't rename in other directory!
1302 if not exist foo echo original file not present anymore
1304 cd .. & rd /s/q foobar
1306 echo ------------ Testing move ------------
1307 mkdir foobar & cd foobar
1310 move foo bar > nul 2>&1
1313 echo file move succeeded
1318 move /Y bar baz > nul 2>&1
1321 echo file move with overwrite succeeded
1324 echo file overwrite impossible!
1330 move baz bazro > nul 2>&1
1333 echo read-only files are moveable
1334 move bazro baz > nul 2>&1
1337 echo read-only file not moved!
1341 move baz rep > nul 2>&1
1344 echo file moved in subdirectory
1348 move rep\baz . > nul 2>&1
1349 move /Y baz baz > nul 2>&1
1351 echo moving a file to itself should be a no-op!
1353 echo moving a file to itself is a no-op
1355 echo ErrorLevel: %ErrorLevel%
1358 echo --- directory move
1362 move baz foo\bar > nul 2>&1
1364 if exist foo\bar\baz\baz2 (
1365 echo simple directory move succeeded
1370 move baz baz > nul 2>&1
1371 echo moving a directory to itself gives error; errlevel %ErrorLevel%
1372 echo ------ dir in dir move
1377 move foo bar > nul 2>&1
1385 cd .. & rd /s/q foobar
1387 echo ------------ Testing mkdir ------------
1389 echo --- md and mkdir are synonymous
1396 echo --- creating an already existing directory/file must fail
1405 echo --- multilevel path creation
1417 mkdir ..\..\..\foo\bar2
1420 mkdir ..\..\..\foo\bar2
1422 rmdir ..\..\..\foo\bar2
1430 echo --- trailing backslashes
1433 if exist foo (rmdir foo & echo dir created
1434 ) else ( echo dir not created )
1436 echo --- invalid chars
1438 echo mkdir ? gives errorlevel %ErrorLevel%
1441 echo mkdir ?\foo gives errorlevel %ErrorLevel%
1444 echo mkdir foo\? gives errorlevel %ErrorLevel%
1445 if exist foo (rmdir foo & echo ok, foo created
1446 ) else ( echo foo not created )
1449 echo mkdir foo\bar\? gives errorlevel %ErrorLevel%
1452 echo bad, foo not created
1456 echo ok, foo\bar created
1462 echo --- multiple directories at once
1463 mkdir foobaz & cd foobaz
1464 mkdir foo bar\baz foobar "bazbaz" .\"zabzab"
1465 if exist foo (echo foo created) else echo foo not created!
1466 if exist bar (echo bar created) else echo bar not created!
1467 if exist foobar (echo foobar created) else echo foobar not created!
1468 if exist bar\baz (echo bar\baz created) else echo bar\baz not created!
1469 if exist bazbaz (echo bazbaz created) else echo bazbaz not created!
1470 if exist zabzab (echo zabzab created) else echo zabzab not created!
1471 cd .. & rd /s/q foobaz
1474 echo mkdir foo\* errorlevel %ErrorLevel%
1475 if exist foo (rmdir foo & echo ok, foo created
1476 ) else ( echo bad, foo not created )
1478 echo ------------ Testing rmdir ------------
1480 rem rd and rmdir are synonymous
1484 if not exist foobar echo dir removed
1488 if not exist foobar echo dir removed
1489 rem Removing nonexistent directory
1492 rem Removing single-level directories
1496 if exist foo echo file not removed
1502 if exist foo echo non-empty dir not removed
1507 if exist foo echo non-empty dir not removed
1514 echo recursive rmdir succeeded
1521 echo foo > foo\bar\brol
1522 rmdir /s /Q foo 2>&1
1524 echo recursive rmdir succeeded
1531 rem multiples directories at once
1532 mkdir foobaz & cd foobaz
1536 rd /s/q foo bar foobar
1537 if not exist foo (echo foo removed) else echo foo not removed!
1538 if not exist bar (echo bar removed) else echo bar not removed!
1539 if not exist foobar (echo foobar removed) else echo foobar not removed!
1540 if not exist bar\baz (echo bar\baz removed) else echo bar\baz not removed!
1541 cd .. & rd /s/q foobaz
1543 echo ------------ Testing pushd/popd ------------
1545 echo --- popd is no-op when dir stack is empty
1548 echo --- pushing non-existing dir
1551 echo --- basic behaviour
1576 echo ------------ Testing attrib ------------
1577 rem FIXME Add tests for archive, hidden and system attributes + mixed attributes modifications
1578 mkdir foobar & cd foobar
1579 echo foo original contents> foo
1582 echo --- read-only attribute
1583 rem Read-only files cannot be altered or deleted, unless forced
1591 echo Read-only file not deleted
1593 echo Should not delete read-only file!
1597 echo Read-only file forcibly deleted
1599 echo Should delete read-only file with del /F!
1603 cd .. & rd /s/q foobar
1604 echo --- recursive behaviour
1605 mkdir foobar\baz & cd foobar
1611 attrib +R l*vel? /S > nul 2>&1
1617 cd .. & rd /s/q foobar
1618 echo --- folders processing
1624 attrib +r baz /s /d > nul 2>&1
1630 rem Oddly windows allows file creation in a read-only directory...
1631 if exist baz\lala (echo file created in read-only dir) else echo file not created
1632 cd .. & rd /s/q foobar
1634 echo ------------ Testing assoc ------------
1635 rem FIXME Can't test error messages in the current test system, so we have to use some kludges
1636 rem FIXME Revise once || conditional execution is fixed
1637 mkdir foobar & cd foobar
1638 echo --- setting association
1646 rem association set system-wide
1647 echo @echo off> tmp.cmd
1648 echo echo +++>> tmp.cmd
1649 echo assoc .foo>> tmp.cmd
1652 echo --- resetting association
1658 rem association removal set system-wide
1659 cmd /c tmp.cmd > baz
1662 cd .. & rd /s/q foobar
1664 echo ------------ Testing ftype ------------
1665 rem FIXME Can't test error messages in the current test system, so we have to use some kludges
1666 rem FIXME Revise once || conditional execution is fixed
1667 mkdir foobar & cd foobar
1668 echo --- setting association
1673 ftype footype=foo_opencmd
1677 rem association set system-wide
1678 echo @echo off> tmp.cmd
1679 echo echo +++>> tmp.cmd
1680 echo ftype footype>> tmp.cmd
1683 echo --- resetting association
1686 rem Removing a file type association doesn't work on XP due to a bug, so a workaround is needed
1687 setlocal EnableDelayedExpansion
1688 set FOO=original value
1691 for /F %%i in ('type baz') do (set FOO=buggyXP)
1692 rem Resetting actually works on wine/NT4, but is reported as failing due to the peculiar test (and non-support for EnabledDelayedExpansion)
1693 rem FIXME Revisit once a grep-like program like ftype is implemented
1694 rem (e.g. to check baz's size using dir /b instead)
1697 rem cleanup registry
1698 echo REGEDIT4> regCleanup.reg
1699 echo.>> regCleanup.reg
1700 echo [-HKEY_CLASSES_ROOT\footype]>> regCleanup.reg
1701 regedit /s regCleanup.reg
1704 cd .. & rd /s/q foobar
1706 echo ------------ Testing CALL ------------
1707 mkdir foobar & cd foobar
1708 echo --- external script
1709 echo echo foo %%1> foo.cmd
1712 echo echo %%1 %%2 > foo.cmd
1714 call foo.cmd foo bar
1721 echo --- internal routines
1722 call :testRoutine :testRoutine
1723 goto :endTestRoutine
1729 call :testRoutineArgs foo
1730 call :testRoutineArgs foo bar
1731 call :testRoutineArgs foo ""
1732 call :testRoutineArgs "" bar
1733 call :testRoutineArgs foo ''
1734 call :testRoutineArgs '' bar
1735 goto :endTestRoutineArgs
1741 echo --- with builtins
1744 if exist foo (echo foo created) else echo foo should exist!
1746 set FOOBAZ_VAR=foobaz
1747 call echo Should expand %FOOBAZ_VAR%
1752 if 1==1 call del batfile
1754 if exist batfile echo batfile shouldn't exist
1755 rem ... but not for 'if' or 'for'
1756 call if 1==1 echo bar 2> nul
1759 call for %%i in (foo bar baz) do echo %%i 2> nul
1761 rem First look for programs in the path before trying a builtin
1762 echo echo non-builtin dir> dir.cmd
1765 rem The below line equates to call (, which does nothing, then the
1766 rem subsequent lines are executed.
1771 rem The below line equates to call if, which always fails, then the
1772 rem subsequent lines are executed. Note cmd.exe swallows all lines
1779 call call call echo passed
1780 cd .. & rd /s/q foobar
1782 echo ------------ Testing SHIFT ------------
1784 call :shiftFun p1 p2 p3 p4 p5
1788 echo '%1' '%2' '%3' '%4' '%5'
1790 echo '%1' '%2' '%3' '%4' '%5'
1792 echo '%1' '%2' '%3' '%4' '%5'
1794 echo '%1' '%2' '%3' '%4' '%5'
1796 echo '%1' '%2' '%3' '%4' '%5'
1798 echo '%1' '%2' '%3' '%4' '%5'
1802 echo ------------ Testing cmd invocation ------------
1803 rem FIXME: only a stub ATM
1804 echo --- a batch file can delete itself
1805 echo del foo.cmd>foo.cmd
1807 if not exist foo.cmd (
1808 echo file correctly deleted
1810 echo file should be deleted!
1813 echo --- a batch file can alter itself
1814 echo echo bar^>foo.cmd>foo.cmd
1815 cmd /q /c foo.cmd > NUL 2>&1
1820 echo file not created!
1823 echo ---------- Testing copy
1826 rem Note echo adds 0x0d 0x0a on the end of the line in the file
1829 echo CCCCCCCCC> file3
1835 echo Passed: Found expected %1
1837 echo Failed: Did not find expected %1
1839 del /q "%1" >nul 2>&1
1841 if not "%1"=="" goto :CheckExist
1846 echo Passed: Did not find %1
1848 echo Failed: Unexpectedly found %1
1849 del /q "%1" >nul 2>&1
1852 if not "%1"=="" goto :CheckNotExist
1855 rem Note: No way to check file size on NT4 so skip the test
1858 echo Failed: File missing when requested filesize check [%2]
1859 goto :ContinueFileSizeChecks
1861 for %%i in (%1) do set filesize=%%~zi
1862 if "%filesize%"=="%2" (
1863 echo Passed: file size check on %1 [%filesize%]
1865 if "%filesize%"=="%%~zi" (
1866 echo Skipping file size check on NT4
1868 echo Failed: file size check on %1 [%filesize% != %2]
1871 :ContinueFileSizeChecks
1874 if not "%1"=="" goto :CheckFileSize
1879 rem -----------------------
1880 rem Simple single file copy
1881 rem -----------------------
1882 rem Simple single file copy, normally used syntax
1883 copy file1 dummy.file >nul 2>&1
1884 if errorlevel 1 echo Incorrect errorlevel
1885 call :CheckExist dummy.file
1887 rem Simple single file copy, destination supplied as two forms of directory
1888 copy file1 dir1 >nul 2>&1
1889 if errorlevel 1 echo Incorrect errorlevel
1890 call :CheckExist dir1\file1
1892 copy file1 dir1\ >nul 2>&1
1893 if errorlevel 1 echo Incorrect errorlevel
1894 call :CheckExist dir1\file1
1896 rem Simple single file copy, destination supplied as fully qualified destination
1897 copy file1 dir1\file99 >nul 2>&1
1898 if errorlevel 1 echo Incorrect errorlevel
1899 call :CheckExist dir1\file99
1901 rem Simple single file copy, destination not supplied
1903 copy ..\file1 >nul 2>&1
1904 if errorlevel 1 echo Incorrect errorlevel
1905 call :CheckExist file1
1908 rem Simple single file copy, destination supplied as nonexistent directory
1909 copy file1 dir2\ >nul 2>&1
1910 if not errorlevel 1 echo Incorrect errorlevel
1911 call :CheckNotExist dir2 dir2\file1
1913 rem -----------------------
1915 rem -----------------------
1916 rem Simple single file copy, destination supplied as two forms of directory
1917 copy file? dir1 >nul 2>&1
1918 if errorlevel 1 echo Incorrect errorlevel
1919 call :CheckExist dir1\file1 dir1\file2 dir1\file3
1921 copy file* dir1\ >nul 2>&1
1922 if errorlevel 1 echo Incorrect errorlevel
1923 call :CheckExist dir1\file1 dir1\file2 dir1\file3
1925 rem Simple single file copy, destination not supplied
1927 copy ..\file*.* >nul 2>&1
1928 if errorlevel 1 echo Incorrect errorlevel
1929 call :CheckExist file1 file2 file3
1932 rem Simple wildcarded file copy, destination supplied as nonexistent directory
1933 copy file? dir2\ >nul 2>&1
1934 if not errorlevel 1 echo Incorrect errorlevel
1935 call :CheckNotExist dir2 dir2\file1 dir2\file2 dir2\file3
1937 rem ------------------------------------------------
1938 rem Confirm overwrite works (cannot test prompting!)
1939 rem ------------------------------------------------
1940 copy file1 testfile >nul 2>&1
1941 copy /y file2 testfile >nul 2>&1
1942 call :CheckExist testfile
1944 rem ------------------------------------------------
1945 rem Test concatenation
1946 rem ------------------------------------------------
1947 rem simple case, no wildcards
1948 copy file1+file2 testfile >nul 2>&1
1949 if errorlevel 1 echo Incorrect errorlevel
1950 call :CheckExist testfile
1952 rem simple case, wildcards, no concatenation
1953 copy file* testfile >nul 2>&1
1954 if errorlevel 1 echo Incorrect errorlevel
1955 call :CheckExist testfile
1957 rem simple case, wildcards, and concatenation
1959 copy file*+fred testfile >nul 2>&1
1960 if errorlevel 1 echo Incorrect errorlevel
1961 call :CheckExist testfile
1963 rem simple case, wildcards, and concatenation
1964 copy fred+file* testfile >nul 2>&1
1965 if errorlevel 1 echo Incorrect errorlevel
1966 call :CheckExist testfile
1968 rem Calculate destination name
1969 copy fred+file* dir1 >nul 2>&1
1970 if errorlevel 1 echo Incorrect errorlevel
1971 call :CheckExist dir1\fred
1973 rem Calculate destination name
1974 copy fred+file* dir1\ >nul 2>&1
1975 if errorlevel 1 echo Incorrect errorlevel
1976 call :CheckExist dir1\fred
1978 rem Calculate destination name (none supplied)
1980 copy ..\fred+..\file* >nul 2>&1
1981 if errorlevel 1 echo Incorrect errorlevel
1982 call :CheckExist fred
1984 copy ..\fr*+..\file1 >nul 2>&1
1985 if errorlevel 1 echo Incorrect errorlevel
1986 call :CheckExist fred
1989 rem ******************************************************************
1990 rem ASCII and BINARY tests
1991 rem Note: hard coded numbers deliberate because need to ensure whether
1992 rem an additional EOF has been added or not. There is no way to handle
1993 rem EOFs in batch, so assume if a single byte appears, its an EOF!
1994 rem ******************************************************************
1996 rem Confirm original sizes of file1,2,3
1997 call :CheckFileSize file1 5 file2 8 file3 11
2001 rem ----------------------------------------------
2002 rem Show concatenation defaults copy to ascii mode
2003 rem ----------------------------------------------
2004 rem Simple default copy source to destination (should not append EOF 5)
2005 copy ..\file1 file1_default >nul 2>&1
2006 call :CheckFileSize file1_default 5
2008 rem Simple binary copy source to destination (should not append EOF 5)
2009 copy /b ..\file1 file1_default2 >nul 2>&1
2010 call :CheckFileSize file1_default2 5
2012 rem Simple ascii copy source to destination (should append EOF 5+1, 8+1, 11+1)
2013 copy /a ..\file1 file1_plus_eof >nul 2>&1
2014 call :CheckFileSize file1_plus_eof 6
2015 copy /a ..\file2 file2_plus_eof >nul 2>&1
2016 call :CheckFileSize file2_plus_eof 9
2017 copy /a ..\file3 file3_plus_eof >nul 2>&1
2018 call :CheckFileSize file3_plus_eof 12
2020 rem Concat 2 files, ascii mode - (only one EOF on the end 5+8+1)
2021 copy /a ..\file1+..\file2 file12_plus_eof >nul 2>&1
2022 call :CheckFileSize file12_plus_eof 14
2024 rem Concat 2 files, binary mode - (no EOF on the end 5+8)
2025 copy /b ..\file1+..\file2 file12_no_eof >nul 2>&1
2026 call :CheckFileSize file12_no_eof 13
2028 rem Concat 2 files, default mode - (one EOF on the end 5+8+1)
2029 copy ..\file1+..\file2 file12_eof2 >nul 2>&1
2030 call :CheckFileSize file12_eof2 14
2032 rem --------------------------------------------------------------
2033 rem Show ascii source copy stops at first EOF, binary does the lot
2034 rem --------------------------------------------------------------
2035 copy file1_plus_eof /b file1_binary_srccopy /b >nul 2>&1
2036 call :CheckFileSize file1_binary_srccopy 6
2038 copy file1_plus_eof /a file1_ascii_srccopy /b >nul 2>&1
2039 call :CheckFileSize file1_ascii_srccopy 5
2041 rem --------------------------------------------------------------
2042 rem Show results of concatenating files (ending in EOFs) and /a /b
2043 rem --------------------------------------------------------------
2045 rem Default and ascii copy reads as ascii, stripping EOFs, so 6-1 + 9-1 + 12-1 + 1
2046 copy file1_plus_eof+file2_plus_eof+file3_plus_eof file123_default_copy >nul 2>&1
2047 call :CheckFileSize file123_default_copy 25
2048 copy /a file1_plus_eof+file2_plus_eof+file3_plus_eof file123_ascii_copy >nul 2>&1
2049 call :CheckFileSize file123_ascii_copy 25
2051 rem In binary mode, we get 3 eofs, so 6 + 9 + 12 = 27
2052 copy /b file1_plus_eof + file2_plus_eof + file3_plus_eof file123_binary_copy >nul 2>&1
2053 call :CheckFileSize file123_binary_copy 27
2055 rem We can select which we want the eofs from by postfixing it with /a or /b
2056 rem so here have first and third with eof, second as ascii 6 + 9-1 + 12
2057 copy file1_plus_eof /b + file2_plus_eof /a + file3_plus_eof /b file123_mixed_copy1 >nul 2>&1
2058 call :CheckFileSize file123_mixed_copy1 26
2060 rem By postfixing the destination with /a, we ask for an ascii destination which appends EOF
2061 rem so here have first and third with eof, second as ascii 6 + 9-1 + 12 + extra EOF
2062 rem Note the delta between this and the previous one also shows that the destination
2063 rem ascii/binary is inherited from the last /a or /b on the line
2064 copy file1_plus_eof /b + file2_plus_eof /a + file3_plus_eof /b file123_mixed_copy2 /a >nul 2>&1
2065 call :CheckFileSize file123_mixed_copy2 27
2067 rem so here have second with eof, first and third as ascii 6-1 + 9 + 12-1
2068 rem Note the delta between the next two also shows that the destination ascii/binary is
2069 rem inherited from the last /a or /b on the line, so the first has an extra EOF
2070 copy file1_plus_eof /a + file2_plus_eof /b + file3_plus_eof /a file123_mixed_copy3 >nul 2>&1
2071 call :CheckFileSize file123_mixed_copy3 26
2072 copy file1_plus_eof /a + file2_plus_eof /b + file3_plus_eof /a file123_mixed_copy4 /b >nul 2>&1
2073 call :CheckFileSize file123_mixed_copy4 25
2075 rem -------------------------------------------------------------------------------------------
2076 rem This shows when concatenating, an ascii destination always adds on an EOF but when we
2077 rem are not concatenating, its a direct copy regardless of destination if being read as binary
2078 rem -------------------------------------------------------------------------------------------
2080 rem All 3 have eof's, plus an extra = 6 + 9 + 12 + eof
2081 copy /b file1_plus_eof + file2_plus_eof + file3_plus_eof file123_mixed_copy5 /a >nul 2>&1
2082 call :CheckFileSize file123_mixed_copy5 28
2084 rem All 2 have eof's, plus an extra = 6 + 12 + eof
2085 copy /b file1_plus_eof + file3_plus_eof file123_mixed_copy6 /a >nul 2>&1
2086 call :CheckFileSize file123_mixed_copy6 19
2088 rem One file has EOF, but doesn't get an extra one, i.e. 6
2089 copy /b file1_plus_eof file123_mixed_copy7 /a >nul 2>&1
2090 call :CheckFileSize file123_mixed_copy7 6
2092 rem Syntax means concatenate so ascii destination kicks in
2093 copy /b file1_plus_eof* file123_mixed_copy8 /a >nul 2>&1
2094 call :CheckFileSize file123_mixed_copy8 7
2099 rem ---------------------------------------
2100 rem Error combinations
2101 rem ---------------------------------------
2102 rem Specify source directory but name is a file
2104 copy file1\ dir1\ >NUL 2>&1
2105 if errorlevel 1 echo Passed: errorlevel invalid check 1
2106 if not errorlevel 1 echo Failed: errorlevel invalid check 1
2107 call :CheckNotExist dir1\file1
2109 rem Overwrite same file
2111 copy file1 file1 >NUL 2>&1
2112 if errorlevel 1 echo Passed: errorlevel invalid check 2
2113 if not errorlevel 1 echo Failed: errorlevel invalid check 2
2115 rem Supply same file identified as a directory
2117 copy file1 file1\ >NUL 2>&1
2118 if errorlevel 1 echo Passed: errorlevel invalid check 3
2119 if not errorlevel 1 echo Failed: errorlevel invalid check 3
2124 echo ------------ Testing setlocal/endlocal ------------
2126 rem Note: setlocal EnableDelayedExpansion already tested in the variable delayed expansion test section
2127 mkdir foobar & cd foobar
2128 echo --- enable/disable extensions
2129 setlocal DisableEXTensions
2130 echo ErrLev: %ErrorLevel%
2132 echo ErrLev: %ErrorLevel%
2133 echo @echo off> tmp.cmd
2134 echo echo ErrLev: %%ErrorLevel%%>> tmp.cmd
2135 rem Enabled by default
2137 cmd /E:OfF /C tmp.cmd
2138 cmd /e:oN /C tmp.cmd
2140 rem FIXME: creating file before setting envvar value to prevent parsing-time evaluation (due to EnableDelayedExpansion not being implemented/available yet)
2141 echo --- setlocal with corresponding endlocal
2142 rem %CD% does not tork on NT4 so use the following workaround
2143 for /d %%i in (.) do set CURDIR=%%~dpnxi
2144 echo @echo off> test.cmd
2145 echo echo %%VAR%%>> test.cmd
2146 echo setlocal>> test.cmd
2147 echo set VAR=localval>> test.cmd
2148 echo md foobar2>> test.cmd
2149 echo cd foobar2>> test.cmd
2150 echo echo %%VAR%%>> test.cmd
2151 echo for /d %%%%i in (.) do echo %%%%~dpnxi>> test.cmd
2152 echo endlocal>> test.cmd
2153 echo echo %%VAR%%>> test.cmd
2154 echo for /d %%%%i in (.) do echo %%%%~dpnxi>> test.cmd
2158 for /d %%i in (.) do echo %%~dpnxi
2162 echo --- setlocal with no corresponding endlocal
2163 echo @echo off> test.cmd
2164 echo echo %%VAR%%>> test.cmd
2165 echo setlocal>> test.cmd
2166 echo set VAR=localval>> test.cmd
2167 echo md foobar2>> test.cmd
2168 echo cd foobar2>> test.cmd
2169 echo echo %%VAR%%>> test.cmd
2170 echo for /d %%%%i in (.) do echo %%%%~dpnxi>> test.cmd
2172 rem %CD% does not tork on NT4 so use the following workaround
2173 for /d %%i in (.) do set CURDIR=%%~dpnxi
2176 for /d %%i in (.) do echo %%~dpnxi
2180 echo --- setlocal within same batch program
2184 rem %CD% does not tork on NT4 so use the following workaround
2185 for /d %%i in (.) do set CURDIR=%%~dpnxi
2192 if "%var1%"=="one" echo Var1 ok 1
2193 if "%var2%"=="two" echo Var2 ok 2
2194 if "%var3%"=="three" echo Var3 ok 3
2195 for /d %%i in (.) do set curdir2=%%~dpnxi
2196 if "%curdir2%"=="%curdir%\foobar2" echo Directory is ok 1
2198 if "%var1%"=="one" echo Var1 ok 1
2199 if "%var2%"=="two" echo Var2 ok 2
2200 if "%var3%"=="" echo Var3 ok 3
2201 for /d %%i in (.) do set curdir2=%%~dpnxi
2202 if "%curdir2%"=="%curdir%\foobar2" echo Directory is ok 2
2204 if "%var1%"=="one" echo Var1 ok 1
2205 if "%var2%"=="" echo Var2 ok 2
2206 if "%var3%"=="" echo Var3 ok 3
2207 for /d %%i in (.) do set curdir2=%%~dpnxi
2208 if "%curdir2%"=="%curdir%" echo Directory is ok 3
2212 echo --- Mismatched set and end locals
2216 rem %CD% does not tork on NT4 so use the following workaround
2217 for /d %%i in (.) do set curdir=%%~dpnxi
2219 echo @echo off> 2set1end.cmd
2220 echo echo %%VAR%%>> 2set1end.cmd
2221 echo setlocal>> 2set1end.cmd
2222 echo set VAR=2set1endvalue1>> 2set1end.cmd
2223 echo cd ..\foodir3>> 2set1end.cmd
2224 echo setlocal>> 2set1end.cmd
2225 echo set VAR=2set1endvalue2>> 2set1end.cmd
2226 echo cd ..\foodir4>> 2set1end.cmd
2227 echo endlocal>> 2set1end.cmd
2228 echo echo %%VAR%%>> 2set1end.cmd
2229 echo for /d %%%%i in (.) do echo %%%%~dpnxi>> 2set1end.cmd
2231 echo @echo off> 1set2end.cmd
2232 echo echo %%VAR%%>> 1set2end.cmd
2233 echo setlocal>> 1set2end.cmd
2234 echo set VAR=1set2endvalue1>> 1set2end.cmd
2235 echo cd ..\foodir3>> 1set2end.cmd
2236 echo endlocal>> 1set2end.cmd
2237 echo echo %%VAR%%>> 1set2end.cmd
2238 echo for /d %%%%i in (.) do echo %%%%~dpnxi>> 1set2end.cmd
2239 echo endlocal>> 1set2end.cmd
2240 echo echo %%VAR%%>> 1set2end.cmd
2241 echo for /d %%%%i in (.) do echo %%%%~dpnxi>> 1set2end.cmd
2243 echo --- Extra setlocal in called batch
2245 rem -- setlocal1 == this batch, should never be used inside a called routine
2249 call %curdir%\2set1end.cmd
2252 for /d %%i in (.) do echo %%~dpnxi
2255 for /d %%i in (.) do echo %%~dpnxi
2258 echo --- Extra endlocal in called batch
2260 rem -- setlocal1 == this batch, should never be used inside a called routine
2264 call %curdir%\1set2end.cmd
2267 for /d %%i in (.) do echo %%~dpnxi
2270 for /d %%i in (.) do echo %%~dpnxi
2273 echo --- endlocal in called function rather than batch pgm is ineffective
2279 call :endlocalroutine
2283 goto :endlocalfinished
2301 cd .. & rd /q/s foobar
2303 echo ------------ Testing Errorlevel ------------
2304 rem WARNING: Do *not* add tests using ErrorLevel after this section
2305 should_not_exist 2> nul > nul
2307 rem nt 4.0 doesn't really support a way of setting errorlevel, so this is weak
2308 rem See http://www.robvanderwoude.com/exit.php
2311 if errorlevel 2 echo errorlevel too high, bad
2312 if errorlevel 1 echo errorlevel just right, good
2313 if errorlevel 01 echo errorlevel with leading zero just right, good
2314 if errorlevel -1 echo errorlevel with negative number OK
2315 if errorlevel 0x1 echo hexa should not be recognized!
2316 if errorlevel 1a echo invalid error level recognized!
2318 echo abc%ErrorLevel%def
2319 if errorlevel 1 echo errorlevel nonzero, bad
2320 if not errorlevel 1 echo errorlevel zero, good
2321 if not errorlevel 0x1 echo hexa should not be recognized!
2322 if not errorlevel 1a echo invalid error level recognized!
2323 rem Now verify that setting a real variable hides its magic variable
2325 echo %ErrorLevel% should be 7
2326 if errorlevel 7 echo setting var worked too well, bad
2328 echo %ErrorLevel% should still be 7
2330 echo ------------ Testing GOTO ------------
2333 echo goto with no leading space worked
2336 echo goto with a leading space worked
2339 echo goto with a leading tab worked
2342 echo goto with a following space worked
2344 echo ------------ Testing PATH ------------
2345 set backup_path=%path%
2352 set path=%backup_path%
2355 echo ------------ Testing combined CALLs/GOTOs ------------
2356 echo @echo off>foo.cmd
2357 echo goto :eof>>foot.cmd
2359 echo echo world>>foo.cmd
2361 echo @echo off>foot.cmd
2362 echo echo cheball>>foot.cmd
2364 echo call :bar>>foot.cmd
2365 echo if "%%1"=="deleteMe" (del foot.cmd)>>foot.cmd
2366 echo goto :eof>>foot.cmd
2369 echo echo barbare>>foot.cmd
2370 echo goto :eof>>foot.cmd
2376 rem Script execution stops after the following line
2399 echo Final message is not output since earlier 'foot' processing stops script execution
2400 echo Do NOT add any tests below this line
2402 echo ------------ Done, jumping to EOF -----------
2404 rem Subroutine to set errorlevel and return
2405 rem in windows nt 4.0, this always sets errorlevel 1, since /b isn't supported
2408 rem This line runs under cmd in windows NT 4, but not in more modern versions.