Reputation: 2199
Time for some command line fu in the least fu conducive shell, cmd.exe
.
How can I perform a summation of integers contained in a file?
You might consider the following to work:
taskkill /f /im rsync.exe
echo %errorlevel% > %temp%/kill_site.log
taskkill /f /im ssh.exe
echo %errorlevel% >> %temp%/kill_site.log
taskkill /f /im 7za.exe
echo %errorlevel% >> %temp%/kill_site.log
set /a errorresult=1
for /F "tokens=*" %%G in (%temp%/kill_site.log) do set /A errorresult=%%G+%errorresult%
But, it appears that %errorresult%
will always be the value before the for
loop during the for
loop. Meaning, the resulting %errorlevel%
always has [the integer value of the last line in %temp%/kill_site.log
] + [the %errorlevel%
set, which is 1
].
In the case of exit codes provided by taskkill
, if taskkill
succeeds in killing an existing process, the exit code is 0
, then resulting %errorresult%
in this case will be 1
. If a process doesn't exist when taskkill
is called to kill it, the exit code is 128
; in this case the %errorresult% will be
129`.
I'd like %errorresult%
to be the total of all integers contained on lines in %temp%/kill_site.log
. How do I do this?
[update]
Thanks to Stephen's answer below, I have a final script as follows that I wanted to include for future reference by other users:
setlocal enabledelayedexpansion
taskkill /f /im rsync.exe
echo %errorlevel% > %temp%/kill_site.log
taskkill /f /im ssh.exe
echo %errorlevel% >> %temp%/kill_site.log
taskkill /f /im 7za.exe
echo %errorlevel% >> %temp%/kill_site.log
set /a errorresult=1
for /F "tokens=*" %%G in (%temp%/kill_site.log) do set /A errorresult=%%G+!errorresult!
if %errorresult% lss 255 sendmail.vbs && eventcreate /l application /so backup_scripts /t warning /id 1 /d "website rsync has to be killed because it was long running."
endlocal
It utilizes endlocal
.
I also just realized this is a bit backwards, as I should be checking if the processes are running previous to taking any invalid action against the non-existent processes, but the question is still resolved. Finding if a specific running process exists with a batch script actually uses a similar method of checking the %errorlevel%
is also quite easy.
Upvotes: 0
Views: 102
Reputation: 130869
Stephan's answer works fine, but there is a simpler method that doesn't require delayed expansion.
The SET /A command does its own expansion of variable names, and it always uses the current value.
set /a errorresult=1
for /F "tokens=*" %%G in (%temp%/kill_site.log) do set /A errorresult=%%G+errorresult
Or better yet
set /a errorresult=1
for /F "tokens=*" %%G in (%temp%/kill_site.log) do set /A errorresult+=%%G
Note - I don't understand why you initialize errorresult to 1. I should think 0 would make more sense.
Upvotes: 1
Reputation: 56188
within a for
loop you need delayed expansion for your variables:
use
SETLOCAL ENABLEDELAYEDEXPANSION
at the beginning of your batchfile and change your for-loop to
for /F "tokens=*" %%G in (%temp%/kill_site.log) do set /A errorresult=%%G+!errorresult!
This is because in your for-loop %errorresult% will always use the value at Parse-time. !errorresult! will use the value at run-time.
Upvotes: 1
Reputation: 2199
Here is a non portable solution, but it is NOT the answer, but may assist others that come across this problem in the future:
taskkill /f /im rsync.exe
echo %errorlevel% > "%temp%/kill_site.log"
set /p res1=< "%temp%/kill_site.log"
echo > "%temp%/kill_site.log"
taskkill /f /im ssh.exe
echo %errorlevel% > "%temp%/kill_site.log"
set /p res2=< "%temp%/kill_site.log"
echo > "%temp%/kill_site.log"
taskkill /f /im 7za.exe
echo %errorlevel% > "%temp%/kill_site.log"
set /p res3=< "%temp%/kill_site.log"
echo > "%temp%/kill_site.log"
set /A errorresult=%res1% + %res2% + %res3%
I have marked this as a community wiki as the question is still pending an answer.
Upvotes: 0