1

I want run a command and sum up the output in a batch file. Here is the code:

@echo off
SETLOCAL ENABLEDELAYEDEXPANSION
SET NoOfCores=0
FOR /F "skip=1 USEBACKQ" %%G IN (`wmic cpu get NumberOfLogicalProcessors`) DO (
    IF NOT "%%G" == "" (
        SET /A NoOfCores = !NoOfCores! + %%G
    )
)
echo NoOfCores:%NoOfCores%
ENDLOCAL

When I run this batch file I am getting correct output along with an ERROR:

Missing operand.
NoOfCores:8

When I run command wmic cpu get NumberOfLogicalProcessors manually, I am getting output like this:

NumberOfLogicalProcessors
4
4

Can someone please tell me how to skip the last blank line in the output?

I have referred several articles about checking blank/null values in IF condition but none seem to be working.

Mofi
  • 46,139
  • 17
  • 80
  • 143
keenUser
  • 1,279
  • 3
  • 16
  • 33

2 Answers2

2

Output of wmic is encoded in UTF-16 Little Endian which causes troubles on parsing by command FOR.

The command FOR interprets the end of the file on conversion from Unicode to single byte encoded text as carriage return carriage return line feed. The erroneous carriage return makes the last line not empty. In the provided batch code this results in IF NOT "%%G" == "" being true as loop variable contains a carriage return. But command SET on evaluating the arithmetic expression interprets the carriage return as whitespace character and therefore there is indeed missing the second operand on addition.

But all this can't be seen on running the batch file in a command prompt window with @echo on in first line as on write to console window every carriage return is removed by stream writer.

For more details see the answers on How to correct variable overwriting misbehavior when parsing output.

One workaround is to first redirect output of wmic into a temporary file and use command TYPE within FOR to process the lines as command TYPE makes a better job on conversion from Unicode to OEM than command FOR. The temporary file is deleted after processing the lines.

@echo off
setlocal EnableDelayedExpansion
%SystemRoot%\System32\wbem\wmic.exe cpu get NumberOfLogicalProcessors >"%TEMP%\NumberOfLogicalProcessors.tmp"
set "NoOfCores=0"
for /F "skip=1" %%G in ('type "%TEMP%\NumberOfLogicalProcessors.tmp"') do set /A NoOfCores+=%%G
del "%TEMP%\NumberOfLogicalProcessors.tmp"
echo NoOfCores: %NoOfCores%
endlocal

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.

  • del /?
  • echo /?
  • endlocal /?
  • for /?
  • set /?
  • setlocal /?
  • type /?
  • wmic cpu get /?
Community
  • 1
  • 1
Mofi
  • 46,139
  • 17
  • 80
  • 143
1

Mofi's answer gives a great explanation of what is going on here and provides a solution for that.

There is an even simpler approach though: placing another for /F loop to parse the output of the first one a second time to get rid of the orphaned carriage-return characters. This is the easiest and most versatile solution for correct parsing of Unicode text.

So here is the code I would use:

@echo off
set /A NoOfCores=0
for /F "skip=1" %%G in ('wmic cpu get NumberOfLogicalProcessors') do (
    for /F %%H in ("%%G") do (
        set /A NoOfCores+=%%G
    )
)
echo NoOfCores: %NoOfCores%

This method is credited to dbenham -- see his answer to Why is the FOR /f loop in this batch script evaluating a blank line? and also his external article WMIC and FOR /F : A fix for the trailing <CR> problem.

Community
  • 1
  • 1
aschipfl
  • 33,626
  • 12
  • 54
  • 99