Reputation: 13
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
?
Upvotes: 1
Views: 814
Reputation: 49096
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.
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.
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.
The loop runs endless as long as copying the file is successful. Is that really wanted?
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.
There is a space character missing between set
and /A
and one more between /A
and count=%count%+1
.
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.
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
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 &
.
Upvotes: 1