Why REM inside a block?

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
miskox
Posts: 553
Joined: 28 Jun 2010 03:46

Why REM inside a block?

#1 Post by miskox » 16 Feb 2018 05:42

Hello all!

I just saw this post viewtopic.php?p=9#p9

Quote:
fc "%file1%" "%file2%">NUL&&(
echo the files are equal
rem keep this rem as last command in the block
)||(
echo the files are different
)
Question: why should that REM line be there?

Thanks.
Saso

npocmaka_
Posts: 512
Joined: 24 Jun 2013 17:10
Location: Bulgaria
Contact:

Re: Why REM inside a block?

#2 Post by npocmaka_ » 16 Feb 2018 07:22

I suppose to avoid setting a command at the end of the block that will exit with something different than 0.If this happens the second block will be executed despite files being identical.

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: Why REM inside a block?

#3 Post by dbenham » 16 Feb 2018 07:39

Perhaps that was the intent, but it does not work that way. REM never sets the ERRORLEVEL - the value that existed before the remark is preserved.

It should not be an issue for that code because the only other command in the block is ECHO, which also preserves the ERRORLEVEL.

If you ever need to explicitly clear the ERRORLEVEL to 0, then you can use any of the following:

Code: Select all

(call )
call;
call,
call=

Dave Benham

npocmaka_
Posts: 512
Joined: 24 Jun 2013 17:10
Location: Bulgaria
Contact:

Re: Why REM inside a block?

#4 Post by npocmaka_ » 16 Feb 2018 07:52

dbenham wrote:
16 Feb 2018 07:39
Perhaps that was the intent, but it does not work that way. REM never sets the ERRORLEVEL - the value that existed before the remark is preserved.

It should not be an issue for that code because the only other command in the block is ECHO, which also preserves the ERRORLEVEL.

If you ever need to explicitly clear the ERRORLEVEL to 0, then you can use any of the following:

Code: Select all

(call )
call;
call,
call=

Dave Benham
Is the call the fastest way? What about type nul or color?

Aacini
Expert
Posts: 1885
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: Why REM inside a block?

#5 Post by Aacini » 16 Feb 2018 08:50

There are several simple commands that can be used to set ERRORLEVEL to zero; further details at this answer (below Table 2). For example: CD . or VOL > NUL. However, in some Microsoft site I saw many years ago they suggested VER > NUL for this purpose.

IMHO the special (and strange) forms of CALL command are confusing...

Antonio

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: Why REM inside a block?

#6 Post by dbenham » 16 Feb 2018 13:28

I find all forms to be cryptic - none of them are obvious as to the intent.

I agree that something like (CALL ) or CALL; is especially mysterious looking, but I actually find that kind of good - it is obvious that we are trying to do something that is unusual, not really related to CALL.

Contrast that with something like CD . >NUL, or VER >NUL, and someone might try to figure out a purpose for those commands (other than clearing ERRORLEVEL)

I find that CALL; or (CALL ) is 10 times faster than the other forms. And the (CALL) command that sets ERRORLEVEL to 1 is even faster :)

For most of the other commands, it is the >NUL that is dramatically slowing things down. But even if you are in a situation where stdout has already been redirected to NUL, the CALL forms are still significantly faster. So I will stick with CALL.

Here is my test suite that times how long it takes to execute each form 10,000 times. I included the (CALL) form that sets ERRORLEVEL to 1 just for timing comparison.

Code: Select all

@echo off
echo Normal
echo --------------------------------
for %%C in (
  "cd ."
  "ver >nul"
  "date /t >nul"
  "time /t >nul"
  "verify >nul"
  "call;"
  "(call )"
  "(call)"
) do call :test %%C

echo(
echo stdout already redirected to nul
echo --------------------------------
for %%C in (
  "cd ."
  "ver"
  "date /t"
  "time /t"
  "verify"
  "call;"
  "(call )"
  "(call)"
) do call :test %%C 3>&1 >nul
exit /b

:test
setlocal enableDelayedExpansion
set "cmd=%~1"
set "t0=%time%"
for /l %%N in (1 1 10000) do %~1
set "t1=%time%"
for /f "tokens=1-4 delims=:.," %%a in ("%t0: =0%") do set /a "t0=(((1%%a*60)+1%%b)*60+1%%c)*100+1%%d-36610100"
for /f "tokens=1-4 delims=:.," %%a in ("%t1: =0%") do set /a "t=(((1%%a*60)+1%%b)*60+1%%c)*100+1%%d-36610100-t0"
if %t% lss 0 set /a t+=24*60*60*100
set "t=    %t%"
echo %t:~-4%0 ms  !cmd! >&3
exit /b
--OUTPUT--

Code: Select all

Normal
--------------------------------
 4720 ms  cd .
 1720 ms  ver >nul
 1610 ms  date /t >nul
 1600 ms  time /t >nul
 1540 ms  verify >nul
  160 ms  call;
  160 ms  (call )
  120 ms  (call)

stdout already redirected to nul
--------------------------------
 4730 ms  cd .
  400 ms  ver
  310 ms  date /t
  300 ms  time /t
  230 ms  verify
  150 ms  call;
  150 ms  (call )
  120 ms  (call)

Dave Benham

npocmaka_
Posts: 512
Joined: 24 Jun 2013 17:10
Location: Bulgaria
Contact:

Re: Why REM inside a block?

#7 Post by npocmaka_ » 16 Feb 2018 15:54

color behaves strangely with this script at least on my machine:

Code: Select all

Normal
--------------------------------
53780 ms  color
 1550 ms  cd .
 1590 ms  ver >nul
 1280 ms  date /t >nul
 1270 ms  time /t >nul
 1250 ms  verify >nul
  670 ms  call;
  690 ms  (call )
  530 ms  (call)

stdout already redirected to nul
--------------------------------
  570 ms  color
 1600 ms  cd .
  880 ms  ver
  610 ms  date /t
  630 ms  time /t
  660 ms  verify
  680 ms  call;
  680 ms  (call )
  510 ms  (call)
probably because color does not affect the console collors when redirected.So is the color>nul the fastest way to set the error level to 0?EDIT when redirected color does not change the errorlevel.

jfl
Posts: 226
Joined: 26 Oct 2012 06:40
Location: Saint Hilaire du Touvet, France
Contact:

Re: Why REM inside a block?

#8 Post by jfl » 25 Feb 2018 12:58

As the cryptic (call)s also confuse me, I usually hide them behind macros:

Code: Select all

set "TRUE.EXE=(call,)"	&:# Macro to silently set ERRORLEVEL to 0
set "FALSE.EXE=(call)"	&:# Macro to silently set ERRORLEVEL to 1
The names come from the eponymous commands that do the very same thing in Unix. I added the .EXE suffix to make it look like it's an external command running.
Then you use them as %TRUE.EXE% or %FALSE.EXE%.


About why having a rem at the end of the parenthesis block...
Maybe this is a useless leftover of a longer comment?
Because if you do want to put comments there, it is important to use REM, instead of :: or :# as we usually do elsewhere.
I don't know why, but such fake labels placed at the end of a parenthesis block cause corruptions in surrounding commands.

Jean-François

pieh-ejdsch
Posts: 239
Joined: 04 Mar 2014 11:14
Location: germany

Re: Why REM inside a block?

#9 Post by pieh-ejdsch » 26 Feb 2018 08:13

setting the errorlevel to 0 is still a lot faster with an if than with a call.

Code: Select all

@echo off
call :loop Normal
echo(
call :loop "stdout already redirected to nul" "3>&1 >nul"
exit /b

:loop
echo %~1
echo --------------------------------
for %%C in (
  "cd ."
  "ver >nul"
  "date /t >nul"
  "time /t >nul"
  "verify >nul"
  "call &&@"
  "call &"
  "call ||@"
  "call;"
  "(call )"
  "call "
  "call||@"
  "call&"
  "call&&@"
  "(call)"
  "call"
  "if 1==1 @"
  "if not 1==1 @"
  "if 1==2 @"
  "set /a a=0"
  "<nul set/p="
  "(set /a a=0)"
  "(2>nul \:)"
  "(2>nul md)"
) do call :test %%C %~2
call :test   "(if 1==2 *)" %~2
call :test   "if 1 equ 2 *" %~2
call :test   "(if 1 equ 2 *)" %~2
call :test   "(if 1 equ 2 rem:)" %~2
call :test   "(2>nul *)" %~2
call :test   "(call&&*)" %~2
exit /b

:test
setlocal enableDelayedExpansion
set "cmd=%~1"
set "t0=%time%"
for /l %%N in (1 1 10000) do %~1
set "t1=%time%"
for /f "tokens=1-4 delims=:.," %%a in ("%t0: =0%") do set /a "t0=(((1%%a*60)+1%%b)*60+1%%c)*100+1%%d-36610100"
for /f "tokens=1-4 delims=:.," %%a in ("%t1: =0%") do set /a "t=(((1%%a*60)+1%%b)*60+1%%c)*100+1%%d-36610100-t0"
if %t% lss 0 set /a t+=24*60*60*100
set "t=    %t%"
%~1
>&3 echo %t:~-4%0 ms  EL: %errorlevel%  %1
exit /b
Result

Code: Select all

Normal
--------------------------------
 4520 ms  EL: 0  "cd ."
 2780 ms  EL: 0  "ver >nul"
 2410 ms  EL: 0  "date /t >nul"
 2430 ms  EL: 0  "time /t >nul"
 2420 ms  EL: 0  "verify >nul"
 1140 ms  EL: 0  "call &&@"
 1120 ms  EL: 0  "call &"
 1120 ms  EL: 0  "call ||@"
 1100 ms  EL: 0  "call;"
 1140 ms  EL: 0  "(call )"
 1110 ms  EL: 0  "call "
  750 ms  EL: 1  "call||@"
  760 ms  EL: 1  "call&"
  750 ms  EL: 1  "call&&@"
  770 ms  EL: 1  "(call)"
  770 ms  EL: 1  "call"
  140 ms  EL: 0  "if 1==1 @"
  140 ms  EL: 0  "if not 1==1 @"
  120 ms  EL: 0  "if 1==2 @"
 1100 ms  EL: 0  "set /a a=0"
 5040 ms  EL: 1  "<nul set/p="
 1130 ms  EL: 0  "(set /a a=0)"
 4130 ms  EL: 0  "(2>nul \:)"
 2720 ms  EL: 1  "(2>nul md)"
  180 ms  EL: 0  "(if 1==2 *)"
  190 ms  EL: 0  "if 1 equ 2 *"
  190 ms  EL: 0  "(if 1 equ 2 *)"
  180 ms  EL: 0  "(if 1 equ 2 rem:)"
 3210 ms  EL: 9009  "(2>nul *)"
  860 ms  EL: 1  "(call&&*)"

stdout already redirected to nul
--------------------------------
 4470 ms  EL: 0  "cd ."
 2380 ms  EL: 0  "ver >nul"
 2050 ms  EL: 0  "date /t >nul"
 1990 ms  EL: 0  "time /t >nul"
 2050 ms  EL: 0  "verify >nul"
 1180 ms  EL: 0  "call &&@"
 1170 ms  EL: 0  "call &"
 1170 ms  EL: 0  "call ||@"
 1290 ms  EL: 0  "call;"
 1480 ms  EL: 0  "(call )"
 1280 ms  EL: 0  "call "
  860 ms  EL: 1  "call||@"
  810 ms  EL: 1  "call&"
  830 ms  EL: 1  "call&&@"
  970 ms  EL: 1  "(call)"
 1050 ms  EL: 1  "call"
  180 ms  EL: 0  "if 1==1 @"
  170 ms  EL: 0  "if not 1==1 @"
  150 ms  EL: 0  "if 1==2 @"
 1210 ms  EL: 0  "set /a a=0"
 3060 ms  EL: 1  "<nul set/p="
 1260 ms  EL: 0  "(set /a a=0)"
 4590 ms  EL: 0  "(2>nul \:)"
 2920 ms  EL: 1  "(2>nul md)"
  170 ms  EL: 0  "(if 1==2 *)"
  190 ms  EL: 0  "if 1 equ 2 *"
  210 ms  EL: 0  "(if 1 equ 2 *)"
  190 ms  EL: 0  "(if 1 equ 2 rem:)"
 3520 ms  EL: 9009  "(2>nul *)"
  960 ms  EL: 1  "(call&&*)"

jeb
Expert
Posts: 1041
Joined: 30 Aug 2007 08:05
Location: Germany, Bochum

Re: Why REM inside a block?

#10 Post by jeb » 26 Feb 2018 08:55

Hi pieh-ejdsch,

looks good, ... until I checked the errorlevel :(

Code: Select all

(call)
echo err=%errorlevel%
if 1==1 @
echo err=%errorlevel%
if not 1==1 @
echo err=%errorlevel%
if 1==2 @
echo err=%errorlevel%
Output wrote:err=1
err=1
err=1
err=1
"IF" is fast, but doesn't affect the errorlevel at all

pieh-ejdsch
Posts: 239
Joined: 04 Mar 2014 11:14
Location: germany

Re: Why REM inside a block?

#11 Post by pieh-ejdsch » 26 Feb 2018 17:56

Yes Jeb - you are right.
I have practically evaluated the error level of the previous command of the script - well.
ok - I did a few more tests, but I can not do anything with IF.
On the other hand, FOR / F loops can produce Errorlevel 1 if an OR condition is appended.
The AND condition does not work for it. This means that setting the errolevel to 0 takes much longer than to 1.
Both are about the same with SET / A - similar to setting the errorlevel to 0 with CALL.
SET / P is extremely slow - takes more than 5 times.
Using CALL to set the errorlevel to 1 takes about 7/10 of the time to set it to 0 with CALL.
Setting this to 1 with a FOR / F loop will require setting CALL to 0 more than 1/10 of the time.
A FOR / F construct to 1 with OR IF also needs barely 3/10 of the CALL at 0 time.

Code: Select all

@echo off
echo .>"%userprofile%\desktop\testfileEL"
call :loop " Normal" 
echo(
call :loop2 " NO change"
del "%userprofile%\desktop\testfileEL"
pause
exit /b
:Loop2
echo %~1
echo --------------------------------
for %%C in (
  "for /f %%%%i in () do rem"
  "(for /f %%%%i in ()do rem:)&&rem:"
  "(for /f %%%%i in () do rem:)"
  "(for %%%%i in () do rem:)||@"
  "(2>nul \:)"
  "if 1==1 @"
  "if not 1==1 @"
  "if 1==2 @"
  "(if 1==2 rem:)||@"
  "(if 1 equ 2 rem:)"
) do call :test %%C
call :test   "(if 1==2 *)"
call :test   "if 1 equ 2 *"
call :test   "(if 1 equ 2 *)"
call :test   "(if 1==2 *)||rem:"
call :test   "(if 1==2 *)&&rem:"
call :test   "(for /f %%%%i in ()do *)&&rem:"
exit /b

:loop
echo %~1
echo --------------------------------
for %%C in (
  "set /a a=0"
  "(set /a a=0)"
  "call &&@"
  "call &"
  "call ||@"
  "(call )"
  "call "
  "<%userprofile%\desktop\testfileEL set/p A="
  "<nul set/p="
  "(2>nul md)"
  "(for /f %%%%i in () do rem:)||rem:"
  "call||@"
  "call&"
  "call&&@"
  "(call)"
  "call"
  "(for /f %%%%i in ()do rem:)||if 1==2 rem:"
  "(for /f %%%%i in ()do rem:)||(@"
  "(for /f %%%%i in ()do rem:)||@"
) do call :test %%C %~2
call :test   "(2>nul *)" %~2
call :test   "(call&&*)" %~2

exit /b

:test
set "cmd=%~1"
set "t0=%time%"
for /l %%N in (1 1 10000) do %~1
)
set "t1=%time%"
for /f "tokens=1-4 delims=:.," %%a in ("%t0: =0%") do set /a "t0=(((1%%a*60)+1%%b)*60+1%%c)*100+1%%d-36610100"
for /f "tokens=1-4 delims=:.," %%a in ("%t1: =0%") do set /a "t=(((1%%a*60)+1%%b)*60+1%%c)*100+1%%d-36610100-t0"
if %t% lss 0 set /a t+=24*60*60*100
set "t=    %t%"
call
%~1
)
set "X=%errorlevel%"
call;
%~1
)
set "Y=%errorlevel%"
if %X% equ %y% (set "option=yes") else set "option= NO"
%~1
)
%EL%
%~1
)
>&3 echo %t:~-4%0 ms  Save = %option%  EL: %errorlevel%  %1
exit /b
Results

Code: Select all

 Normal
--------------------------------
 1290 ms  Save = yes  EL: 0  "set /a a=0"
 1190 ms  Save = yes  EL: 0  "(set /a a=0)"
 1420 ms  Save = yes  EL: 0  "call &&@"
 1470 ms  Save = yes  EL: 0  "call &"
 1220 ms  Save = yes  EL: 0  "call ||@"
 1520 ms  Save = yes  EL: 0  "(call )"
 1420 ms  Save = yes  EL: 0  "call "
 7950 ms  Save = yes  EL: 0  "<C:\Users\Philipp\desktop\testfileEL set/p A="
 5390 ms  Save = yes  EL: 1  "<nul set/p="
 2470 ms  Save = yes  EL: 1  "(2>nul md)"
 1760 ms  Save = yes  EL: 1  "(for /f %i in () do rem:)||rem:"
  850 ms  Save = yes  EL: 1  "call||@"
  910 ms  Save = yes  EL: 1  "call&"
  950 ms  Save = yes  EL: 1  "call&&@"
  910 ms  Save = yes  EL: 1  "(call)"
  920 ms  Save = yes  EL: 1  "call"
  330 ms  Save = yes  EL: 1  "(for /f %i in ()do rem:)||if 1==2 rem:"
  130 ms  Save = yes  EL: 1  "(for /f %i in ()do rem:)||(@"
  140 ms  Save = yes  EL: 1  "(for /f %i in ()do rem:)||@"
 4070 ms  Save = yes  EL: 9009  "(2>nul *)"
  840 ms  Save = yes  EL: 1  "(call&&*)"

 NO change
--------------------------------
  130 ms  Save =  NO  EL: 0  "for /f %i in () do rem"
  190 ms  Save =  NO  EL: 0  "(for /f %i in ()do rem:)&&rem:"
  130 ms  Save =  NO  EL: 0  "(for /f %i in () do rem:)"
  130 ms  Save =  NO  EL: 0  "(for %i in () do rem:)||@"
 3680 ms  Save =  NO  EL: 0  "(2>nul \:)"
  140 ms  Save =  NO  EL: 0  "if 1==1 @"
  140 ms  Save =  NO  EL: 0  "if not 1==1 @"
  130 ms  Save =  NO  EL: 0  "if 1==2 @"
  190 ms  Save =  NO  EL: 0  "(if 1==2 rem:)||@"
  190 ms  Save =  NO  EL: 0  "(if 1 equ 2 rem:)"
  190 ms  Save =  NO  EL: 0  "(if 1==2 *)"
  180 ms  Save =  NO  EL: 0  "if 1 equ 2 *"
  190 ms  Save =  NO  EL: 0  "(if 1 equ 2 *)"
  220 ms  Save =  NO  EL: 0  "(if 1==2 *)||rem:"
 1560 ms  Save =  NO  EL: 0  "(if 1==2 *)&&rem:"
  160 ms  Save =  NO  EL: 0  "(for /f %i in ()do *)&&rem:"

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: Why REM inside a block?

#12 Post by dbenham » 26 Feb 2018 23:16

Wow, the FOR /F method for setting to 1 is wicked fast compared to other methods :!: :shock:
But talk about cryptic and ungainly code :?

SET /A is no good for setting to 0 if the extension is .BAT - it only works with .CMD extension.
And there is no need for the /A option - SET A=0 works just as well
Also, the speed must be dependent on the size of the environment space.


Dave Benham

jeb
Expert
Posts: 1041
Joined: 30 Aug 2007 08:05
Location: Germany, Bochum

Re: Why REM inside a block?

#13 Post by jeb » 27 Feb 2018 03:04

pieh-ejdsch wrote:
26 Feb 2018 17:56
On the other hand, FOR / F loops can produce Errorlevel 1 if an OR condition is appended.
That's cool :D :idea:
I tested OR and AND with IF and parenthesis and I also tested FOR, but not in the right combination to find your solution. :(
pieh-ejdsch wrote:
26 Feb 2018 17:56
Using CALL to set the errorlevel to 1 takes about 7/10 of the time to set it to 0 with CALL.
Setting this to 1 with a FOR / F loop will require setting CALL to 0 more than 1/10 of the time.
A FOR / F construct to 1 with OR IF also needs barely 3/10 of the CALL at 0 time.
This part seems to be the result of the measures, but it's wrong as the measures itself are wrong.

We measured with the construct

Code: Select all

for /l %%N in (1 1 10000) do %~1
But this construct parses the command only once and executes it from the cached command block 10000 times.
Therefore the FOR-Set-Trick seems to be very fast compared to (CALL), but in reallity their exectuion times are nearly equal.

I modified the :test function, it uses now an external batch file for the measure and it also tests, if the command has any effect to the errorlevel at all.

Code: Select all

:test
set "cmd=%~1"
setlocal enableDelayedExpansion
set "effectiveErrorlevel=XX"

(echo !cmd!) > cmdTest.bat
(call)
call cmdTest.bat
if %errorlevel%==0 set effectiveErrorlevel=0
(call )
call cmdTest.bat
if %errorlevel% NEQ 0 set effectiveErrorlevel=1

if "!effectiveErrorlevel!" == "XX" (
    echo ERROR: Has no effect "!cmd!"
    exit /b
)

(
    echo set "t0=%%time%%"
    for /l %%N in (1 1 10000) do (
        (echo !cmd!)
    )
    echo set "t1=%%time%%"
)  > cmdTest.bat
call cmdTest.bat

for /f "tokens=1-4 delims=:.," %%a in ("%t0: =0%") do set /a "t0=(((1%%a*60)+1%%b)*60+1%%c)*100+1%%d-36610100"
for /f "tokens=1-4 delims=:.," %%a in ("%t1: =0%") do set /a "t=(((1%%a*60)+1%%b)*60+1%%c)*100+1%%d-36610100-t0"
if %t% lss 0 set /a t+=24*60*60*100
set "t=    %t%"

>&3 echo %t:~-4%0 ms  EL: %effectiveErrorlevel%  !cmd!
exit /b
The "new" results are

Code: Select all

Normal
--------------------------------
 4770 ms  EL: 0  cd .
 4070 ms  EL: 0  ver >nul
 4010 ms  EL: 0  date /t >nul
 4050 ms  EL: 0  time /t >nul
 4060 ms  EL: 0  verify >nul
 2890 ms  EL: 0  call &&@
 2750 ms  EL: 0  call &
 2870 ms  EL: 0  call ||@
 2930 ms  EL: 0  call;
 2590 ms  EL: 0  (call )
 2740 ms  EL: 0  call
 2430 ms  EL: 1  call||@
 2430 ms  EL: 1  call&
 2450 ms  EL: 1  call&&@
 2480 ms  EL: 1  (call)
 2450 ms  EL: 1  call
ERROR: Has no effect "if 1==1 @"
ERROR: Has no effect "if not 1==1 @"
ERROR: Has no effect "if 1==2 @"
ERROR: Has no effect "set /a a=0"
 5710 ms  EL: 1  <nul set/p=
ERROR: Has no effect "(set /a a=0)"
 4030 ms  EL: 1  (2>nul \:)
 3930 ms  EL: 1  (2>nul md)
 2530 ms  EL: 1  (for /f %%i in () do .)||@
ERROR: Has no effect "rem"

stdout already redirected to nul
--------------------------------
 5410 ms  EL: 0  cd .
 3570 ms  EL: 0  ver >nul
 3200 ms  EL: 0  date /t >nul
 3050 ms  EL: 0  time /t >nul
 3180 ms  EL: 0  verify >nul
 2610 ms  EL: 0  call &&@
 2550 ms  EL: 0  call &
 2610 ms  EL: 0  call ||@
 2760 ms  EL: 0  call;
 2580 ms  EL: 0  (call )
 2620 ms  EL: 0  call
 2450 ms  EL: 1  call||@
 2470 ms  EL: 1  call&
 2480 ms  EL: 1  call&&@
 2480 ms  EL: 1  (call)
 2490 ms  EL: 1  call
ERROR: Has no effect "if 1==1 @"
ERROR: Has no effect "if not 1==1 @"
ERROR: Has no effect "if 1==2 @"
ERROR: Has no effect "set /a a=0"
 5040 ms  EL: 1  <nul set/p=
ERROR: Has no effect "(set /a a=0)"
 4170 ms  EL: 1  (2>nul \:)
 3930 ms  EL: 1  (2>nul md)
 2670 ms  EL: 1  (for /f %%i in () do .)||@
ERROR: Has no effect "rem"
In german you can say "Wer mißt, mißt Mist" translated to something like "Who measures measures rubbish!" but "rubbish" is in german the same word like measure :D

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: Why REM inside a block?

#14 Post by dbenham » 27 Feb 2018 06:49

Good catch jeb, and nice :test design :D
Although both tests are legitimate - Sometimes you need to set or clear the ERRORLEVEL within a large FOR loop.
jeb wrote:
27 Feb 2018 03:04
In german you can say "Wer mißt, mißt Mist" translated to something like "Who measures measures rubbish!" but "rubbish" is in german the same word like measure :D
Indeed - you forgot to remove the >nul from your commands in the 2nd round of tests with stdout already redirected :lol:

Here are some results from my home machine:

Code: Select all

Normal
--------------------------------
 5520 ms  EL: 0  date /t >nul
 5560 ms  EL: 0  time /t >nul
 5480 ms  EL: 0  verify >nul
 5090 ms  EL: 0  call;
 4990 ms  EL: 0  (call )
 4560 ms  EL: 1  (call)
 4020 ms  EL: 1  (for /f %%a in () do rem.)||rem

stdout already redirected to nul
--------------------------------
 3830 ms  EL: 0  date /t
 3880 ms  EL: 0  time /t
 3890 ms  EL: 0  verify
 4170 ms  EL: 0  call;
 4080 ms  EL: 0  (call )
 3680 ms  EL: 1  (call)
 3160 ms  EL: 1  (for /f %%a in () do rem.)||rem
 
I am surprised that even commands that don't require redirection show a significant improvement in performance if stdout is already redirected to nul.
I ran the script a number of times, and the results were consistent.

miskox
Posts: 553
Joined: 28 Jun 2010 03:46

Re: Why REM inside a block?

#15 Post by miskox » 12 Apr 2018 02:31

Hello all!

Sorry for a 'short' (long?) delay in giving an answer (I was ill, my wife had a surgery... so priorities change).

Thank you all for your tests, thoughts...

Saso

Post Reply