1

My batch script is written for measuring how much traffic between two PCs a network can handle. So the script determines the size of a file and send it from one PC to another and count how many times this works. But there is a weird problem on the calculation of total number of successfully transfered bytes. The value of environment variable asdf3 printed via echo after the calculation seems to be inaccurate.

echo hat %count% mal geklappt
echo size: %menge% byte
set /a asdf3=%count%*%menge%
echo es wurden %asdf3% byte verschoben

The lines above produce this output:

hat 58 mal geklappt
size: 30245 byte
es wurden 2722050 byte verschoben

It should be 1754210 (58 * 30245) if my math is okay.

The variables are initialized like this:

set file="test.odt"
FOR /F "usebackq" %%A IN ('%file%') DO set /A menge=%%~zA

set /A count=0
:marker
COPY /Y /V %file% \\%name%\Users\public
if 0==%errorlevel% (
    set/Acount=%count%+1
    goto :marker
)

Why does evaluation of the simple arithmetic expression in batch file produce 2722050 instead of expected result 1754210?

Mofi
  • 38,783
  • 14
  • 62
  • 115
AlfaTron
  • 13
  • 3
  • can't reproduce such behaviour, but you need a space in `set /a count=%count%+1`. btw is the same `set /a count=count+1` or better `set /a count+=1` – elzooilogico Sep 04 '18 at 11:04
  • This will not work if you have large files as cmd use 32bit only. – Gerhard Sep 04 '18 at 12:53

1 Answers1

1
  1. Do not use the syntax set variable="value". It is better to use the syntax set "variable=value" and reference the environment variable value as is or concatenated with a fixed string or another environment variable reference enclosed in double quotes. Please take also a look on answer on Why is no string output with 'echo %var%' after using 'set var = text' on command line? It explains with even more details why it is better to use set "variable=value" with first " left to variable name.

  2. Do not use for /F designed for processing a text file line by line, a string or captured output of a command line to just get a property of a file.

  3. Do not use set /A which results in interpreting the rest of the line as an arithmetic expression to just define an environment variable which is always of type string in memory with a value.

  4. The loop runs endless as long as copying the file is successful. Is that really wanted?

  5. Avoid usage of %errorlevel% with command IF as there is the syntax if errorlevel X for testing if exit code of previous command or application is greater or equal X or if not errorlevel X for testing if exit code of previous command is lower than X which means usually equal 0 as commands and applications do not exist with a negative value.

  6. There is a space character missing between set and /A and one more between /A and count=%count%+1.

  7. The help output on running set /? in a command prompt window explains for set /A that environment variables can be referenced within an arithmetic expression with just their name without % or ! around as long as the environment variable name does not contain an arithmetic operator, a delimiter like a space or a comma and can't be mistakenly interpreted as integer number.

  8. Windows command processor uses 32-bit signed integer arithmetic and so the value range -2147483648 to +2147483647. This means in combination with file size that the value range is limited to 2 GiB before a not handled or reported overflow occurs on evaluation of the arithmetic expression resulting nearly always in unexpected results. For more details see: weird results with IF

  9. There is no need to specify on GOTO command line the label with colon at beginning except for special label :EOF. For details see Where does GOTO :EOF return to?

Here is your code rewritten with no extra code to work around the 32-bit signed integer limitation.

set "name=127.0.0.1"
set "file=test.odt"
for %%A in ("%file%") do set "menge=%%~zA"
set "count=0"

:marker
if %count% == 100 goto Output
COPY /Y /V "%file%" "\\%name%\Users\public"
if not errorlevel 1 set /A "count+=1" & goto marker

:Output
echo hat %count% mal geklappt
echo size: %menge% bytes
set /A asdf3=count * menge
echo es wurden %asdf3% bytes verschoben

For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.

  • copy /?
  • echo /?
  • for /?
  • goto /?
  • if /?
  • set /?

See also Single line with multiple commands using Windows batch file for an explanation of operator &.

Mofi
  • 38,783
  • 14
  • 62
  • 115
  • Thanks for the help now the script works and yes the loop is designed to be endless because i want the system to crash just to look at the maximum speed it can provide. – AlfaTron Sep 05 '18 at 08:31