Using the For command in Batch file - for-loop

I am trying to get the freespace on a hard drive, and then compare it to a value, (to make sure we are not running out of disk space).
I can get it all to work except the final comparison. I am assuming it is because of the format that the free space value is being stored in, but I am not sure how to adjust my code.
My Code:
for /f "usebackq delims== tokens=2" %%x in (`wmic logicaldisk where "DeviceID='W:'" get FreeSpace /format:value`) do set FreeSpace=%%x
If %FreeSpace% LEQ 1000000000 (
echo %FreeSpace% is Less Than 1G of free space
pause
) else (
echo %FreeSpace% is Greater than 1G of free space
pause
)
I want to know if the freespace is greater or less than 1GB. However, it always tells me that it is lower, no matter what value I use for comparison.

Related

free disk space via cmd batch file

need a cmd command to use it in batch file to get free disk space on C drive after and before removing some folders in .txt format or need to know a space for specific folders and also export it in .txt folder
Since cmd.exe's set /A-math is limited to signed 32bit integers, you could get into trouble calculating free space on an empty 4TB drive. A way around is to use PowerShell for the calcuation.
#Echo off
For /f "tokens=2 delims==" %%A in (
'wmic logicaldisk where "DeviceID='C:'" get FreeSpace /format:value'
) Do Set FS1=%%A
:: Delete something
Del /F /A /Q /S "%tmp%\*" >Nul 2>&1
For /f "tokens=2 delims==" %%A in (
'wmic logicaldisk where "DeviceID='C:'" get FreeSpace /format:value'
) Do Set FS2=%%A
set FS
:: Let PowerShell do the calculating
powershell.exe "\"{0,10} GB freed\" -f [math]::round(($env:FS2-$env:FS1)/(1GB),2)"
Sample output:
FS1=87454994432
FS2=85188575232
2,11 GB freed

Run Disk Cleanup When fsutil returns under a certain size

I would like a fully automated way of running disk cleanup when fsutil volume diskfree c: returns under, lets say, 50gb. Currently, I have used cleanmgr /sageset:1 and stored my settings, so the process is half automated. But when it returns the amount of space free, is there any way for windows to read this. Keep in mind this will be in a batch file, so I cannot manually view this. Thanks for any help!
#echo off
setlocal
set "pad=000000000000000"
set "NeededSpace=%pad%4294967296"
for /f "delims== tokens=2" %%x in (
'wmic logicaldisk where "DeviceID='C:'" get FreeSpace /format:value'
) do for %%y in (%%x) do set "FreeSpace=%pad%%%y"
if "%FreeSpace:~-15%" geq "%NeededSpace:~-15%" echo Drive has at least 4 GB free space.

How to get the Percentage of memory utilization using WMIC in batch script?

I am not getting the result for Percentage of memory utilization in batch script using only W MIC. I am getting only total memory and free memory in bytes.
So how to a get those in Megabytes and how to calculate percentage of memory utilization?
Code :-
#echo off
setlocal enabledelayedexpansion
set Times=0
for /f "skip=1" %%p in ('wmic cpu get loadpercentage') do (
set Cpusage!Times!=%%p
set /A Times+=1
)
echo CPU Percentage = %Cpusage0%%%
set Times=0
for /f "skip=1" %%p in ('wmic ComputerSystem get TotalPhysicalMemory') do (
set totalMem!Times!=%%p
set /A Times+=1
)
set Times=0
for /f "skip=1" %%p in ('wmic OS get FreePhysicalMemory') do (
set availableMem!Times!=%%p
set /A Times+=1
)
set Times=0
for /f "skip=1" %%p in ('wmic OS get FreePhysicalMemory ^|findstr physical') do (
set /a UsedMem= totalMem - availableMem
set usedMem!Times!=%%p
set /A Times+=1
)
set /a usedpercent=(usedMem*100)/totalMem
echo Free MEMORY = %availableMem0% Bytes
echo Total MEMORY = %totalMem0% Bytes
echo Used MEMORY = %UsedMem0% Bytes
echo Memory Utilization = %usedpercent0%%%
pause
setlocal enabledelayedexpansion should be used usually only once in a batch file if there is no real necessity to use setlocal multiple times. This command does not just enable delayed expansion mode. It always copies also the entire current environment table (which can be up to 64 MB), the current states of command extension and delayed expansion, and the current directory path on stack (memory). The number of such environment pushes on stack is not unlimited. At least use endlocal between to avoid an early exit of batch processing because of a stack overflow. For more details see the answers on:
Echoing a URL in Batch
Why is my cd %myVar% being ignored?
Even 64-bit Windows command processor (cmd.exe) uses 32-bit signed integers. Therefore the value range is limited to -2.147.483.648 to +2.147.483.647. In other words arithmetic operations with 2 GB and more can't be done without integer overflows producing wrong results.
Here is a commented batch file which does not work for all possible installed RAM configurations, but works for those which are typical in year 2016: 2 GB, 4 GB, 8 GB, 16 GB and 32 GB.
#echo off
rem Note: KB = KiB, MB = MiB and GB = GiB in this batch file, see
rem https://en.wikipedia.org/wiki/Byte for details on GiB.
rem Create a copy of current environment variables. Enabling additionally
rem delayed environment variable expansion is not required for this task.
setlocal EnableExtensions DisableDelayedExpansion
rem The command WMIC with the parameters CPU GET LoadPercentage outputs
rem one line per processor. The output of WMIC is in UTF-16 LE with BOM.
rem The output is redirected to a temporary file which is printed by
rem command TYPE to STDOUT which makes a better job on UNICODE to ASCII
rem conversion as command FOR. Note: 1 processor can have 1 or more cores.
set "CpuUsage=0"
set "Processors=0"
%SystemRoot%\System32\wbem\wmic.exe CPU GET LoadPercentage >"%TEMP%\cpu_usage.tmp"
for /F "skip=1" %%P in ('type "%TEMP%\cpu_usage.tmp"') do (
set /A CpuUsage+=%%P
set /A Processors+=1
)
del "%TEMP%\cpu_usage.tmp"
rem Calculate the CPU usage as percentage value of all processors.
set /A CpuUsage/=Processors
goto GetTotalMemory
rem Output of WMIC is in UTF-16 LE with BOM. The interpretation of this
rem output in ASCII/OEM can result in processing three lines instead of
rem just two with third line being just a carriage return. Therefore exit
rem each loop after assigning the value of second line to the variable.
:GetTotalMemory
for /F "skip=1" %%M in ('%SystemRoot%\System32\wbem\wmic.exe ComputerSystem GET TotalPhysicalMemory') do set "TotalMemory=%%M" & goto GetAvailableMemory
:GetAvailableMemory
for /F "skip=1" %%M in ('%SystemRoot%\System32\wbem\wmic.exe OS GET FreePhysicalMemory') do set "AvailableMemory=%%M" & goto ProcessValues
rem Total physical memory is in bytes which can be greater 2^31 (= 2 GB)
rem Windows command processor performs arithmetic operations always with
rem 32-bit signed integer. Therefore 2 GB or more installed physical
rem memory exceeds the bit width of a 32-bit signed integer and arithmetic
rem calculations are wrong on 2 GB or more installed memory. To avoid
rem the integer overflow, the last 6 characters are removed from bytes
rem value and the remaining characters are divided by 1073 to get the
rem number of GB. This workaround works only for physical RAM being
rem an exact multiple of 1 GB, i.e. for 1 GB, 2 GB, 4 GB, 8 GB, ...
rem 1 GB = 1.073.741.824 bytes = 2^30
rem 2 GB = 2.147.483.648 bytes = 2^31
rem 4 GB = 4.294.967.296 bytes = 2^32
rem 8 GB = 8.589.934.592 bytes = 2^33
rem 16 GB = 17.179.869.184 bytes = 2^34
rem 32 GB = 34.359.738.368 bytes = 2^35
rem But there is one more problem at least on Windows XP x86. About 50 MB
rem of RAM is subtracted as used by Windows itself. This can be seen in
rem system settings when 1.95 GB is displayed although 2 GB is installed.
rem Therefore add 50 MB before dividing by 1073.
:ProcessValues
set "TotalMemory=%TotalMemory:~0,-6%"
set /A TotalMemory+=50
set /A TotalMemory/=1073
rem The total memory in GB must be multiplied by 1024 to get the
rem total physical memory in MB which is always small enough to
rem be calculated with a 32-bit signed integer.
set /A TotalMemory*=1024
rem The available memory is in KB and therefore there is
rem no problem with value range of 32-bit signed integer.
set /A AvailableMemory/=1024
rem So the used memory in MB can be determined easily.
set /A UsedMemory=TotalMemory - AvailableMemory
rem It is necessary to calculate the percentage value in MB instead of
rem KB to avoid a 32-bit signed integer overflow on 32 GB RAM and nearly
rem entire RAM is available because used is just a small amount of RAM.
set /A UsedPercent=(UsedMemory * 100) / TotalMemory
if "%Processors%" == "1" (
set "ProcessorInfo="
) else (
set "ProcessorInfo= of %Processors% processors"
)
echo CPU percentage: %CpuUsage% %%%ProcessorInfo%
echo Free memory: %AvailableMemory% MB
echo Total memory: %TotalMemory% MB
echo Used memory: %UsedMemory% MB
echo Memory usage: %UsedPercent% %%
rem Discard the current environment variable table and restore previous
rem environment variables. The states of command processor extension
rem (default: ON) and delayed expansion (default: OFF) as well as the
rem original current directory are restored by this command although
rem not modified at all by the commands above.
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 /?
goto /?
rem /?
setlocal /?
set /?
type /?
wmic /?
wmic CPU get /?
wmic OS get /?
wmic ComputerSystem get /?
TotalPhysicalMemory property of Win32_ComputerSystem class (in bytes, uint64 data type) overreachs set /A batch file integer arithmetic limitation (see set command): it's limited to 32-bits of precision (corresponds to uint32 data type) i.e. cca ±2 gibibytes (GiB).
Let's capture output from Systeminfo command which is in mebibytes (MiB):
==> systeminfo | find /I "Physical Memory"
Total Physical Memory: 8 137 MB
Available Physical Memory: 4 210 MB
==>
therefore set /A should suffice: 32-bit limitation is overwhelmed.
Explanation in rem comments:
#ECHO OFF >NUL
SETLOCAL EnableExtensions
echo(---
set "_memo_total="
rem unfortunately, next command is (supposedly) locale dependent
for /F "tokens=1,* delims=:" %%G in ('
systeminfo^|find /I "Physical Memory"
') do (
set "_memo_inuse="
rem remove spaces including no-break spaces
for %%g in (%%H) do if /I NOT "%%g"=="MB" set "_memo_inuse=!_memo_inuse!%%g"
if defined _memo_total ( set "_memo_avail=!_memo_inuse!"
) else ( set "_memo_total=!_memo_inuse!" )
echo !_memo_inuse! [MB] %%G
)
set /A "_memo_inuse=_memo_total - _memo_avail"
rem in integer arithmetics: calculate percentage multipled by 100
set /A "_perc_inuse=10000 * _memo_inuse / _memo_total"
set /A "_perc_avail=10000 * _memo_avail / _memo_total"
rem debugging: mostly 9999 as `set /A` trucates quotients instead of rounding
set /A "_perc__suma=_perc_inuse + _perc_avail
echo(---
call :formatpercent _perc_avail
call :formatpercent _perc_inuse
call :formatpercent _perc__suma
rem display results
set _
ENDLOCAL
goto :eof
:formatpercent
rem simulates division by 100
rem input : variable NAME (i.e. passed by reference)
rem it's value could vary from 0 to 10000 format mask ####0
rem output: variable VALUE
rem respectively vary from .00 to 100.00 format mask ###.00
if NOT defined %1 goto :eof
SETLOCAL EnableDelayedExpansion
set "aux5= !%1!"
set "aux5=%aux5:~-5%"
rem repair unacceptable format mask ###.#0 to ###.00
set "auxx=%aux5:~3,1%
if "%auxx%"==" " set "aux5=%aux5:~0,3%0%aux5:~4%"
REM rem change format mask from ###.00 to common ##0.00
REM set "auxx=%aux5:~2,1%
REM if "%auxx%"==" " set "aux5=%aux5:~0,2%0%aux5:~3%"
set "aux6=%aux5:~0,3%.%aux5:~3%"
ENDLOCAL&set "%1=%aux6%"
goto :eof
Output:
==> D:\bat\SO\37338476a.bat
---
8137 [MB] Total Physical Memory
4166 [MB] Available Physical Memory
---
_memo_avail=4166
_memo_inuse=3971
_memo_total=8137
_perc_avail= 51.19
_perc_inuse= 48.80
_perc__suma= 99.99
==>
Accuracy, tolerance (measured with 8 GiB installed memory): ==> good
Capacity=8589934592                from Win32_PhysicalMemory class == 8 GiB
TotalPhysicalMemory=8531865600     from Win32_ComputerSystem class == 8136.62 MiB
Total Physical Memory:   8 137 MB from systeminfo command == 8137 MiB
Response time (systeminfo is considerably slower than wmic): ==> poor
you can alter the output to fit your needs:
#if (#X)==(#Y) #end /* JScript comment
#echo off
cscript //E:JScript //nologo "%~f0"
exit /b %errorlevel%
#if (#X)==(#Y) #end JScript comment */
var aBytes=GetObject('winmgmts:').ExecQuery('Select * from Win32_PerfFormattedData_PerfOS_Memory').ItemIndex(0).AvailableBytes;
var tBytes=GetObject('winmgmts:').ExecQuery('Select * from Win32_ComputerSystem').ItemIndex(0).TotalPhysicalMemory;
WScript.Echo("available:"+aBytes+"\ntotal:"+tBytes);
var totalMemoryUsed=(tBytes-aBytes)*100/tBytes;
WScript.Echo("used in % -"+totalMemoryUsed);

Disk size in Windows for particular drive

I want to know disk available size for particular drive say D, in GB.
I am using below wmic command,
wmic logicaldisk get size,freespace,caption
but it is giving info about each drive, I want for particular drive only and that even in GB.
for /f "delims=" %%a in ('wmic logicaldisk where ^"DeviceID^=^'D:^'^" get size^,freespace^,caption /format:Wmiclivalueformat.xsl^|find "="') do #set %%a
As the numbers could be pretty big and overflows the integers you can get get the free space in GB by getting a substring (be grateful that this requires only division by powers of 10 - though it's not pretty accurate as the real division should be by 1024):
set freespaceinGB=%freespace:~0,-10%
set freespaceinGB_MOD=%freespace:~-10,-8%
echo %freespaceinGB%,%freespaceinGB_MOD%
This dual routine shows the free space on all drives. You can use the main batch file to find the space free on a single drive.
#echo off
for %%A in (A B C D E F G H I J K L M N O P Q R S T U V W X Y Z) do if exist %%A:\ call :bytesfree.bat %%A
pause
goto :EOF
:: Below is the batch file that returns the freespace from the letter in `%1`
#echo off
:bytesfree.bat - Salmon Trout
for /f "tokens=1-3 delims= " %%A in ('dir %1: ^| find "bytes free"') do set bytesfree="%%C"
echo Wscript.echo Formatnumber(eval(WScript.Arguments(0)/1073742268), 2, True,, False) > "%temp%\Calculate.vbs"
for /f "delims=" %%A in ('cscript //nologo "%temp%\Calculate.vbs" %bytesfree%') do set GBfree=%%A & del "%temp%\Calculate.vbs"
set "GBFree= %GBFRee%"
set GBFree=%GBFRee:~-12%
echo %1 %GBfree% GB free
goto :EOF
If you know the VB script then Check this Microsoft link this might resolve your issue.
http://technet.microsoft.com/en-us/library/ee198873.aspx
You just need to copy that code in notepad and save it as .vbs format and execute the file from commandline. command will be like this. cscript filename.vbs
I have a batch file that verifies HDD, Mem, OS and CPU arch, I ripped it a bit to fit your needs. Just set the wanted drive followed by :.
To convert the bytes to GB, I first trim in 1000 until the value can fit in 32bits and only then I divide in 1024. (cmd can only handle 32 bit integers).
#echo off setlocal EnableDelayedExpansion
rem UNIT is used to convert from Bytes to GB
rem 0 - B, 1 - KB, 2 - MB, 3 - GB
SET DRIVE="C:"
REM check all local drives for minimum space requirement
:Local_Drives_space_check
for /F "skip=1 tokens=1,2" %%a in ('wmic LogicalDisk Where DeviceID^=!DRIVE! Get FreeSpace') do (
if not "%%b"=="" (
set /A UNIT=0
set _tmp=%%a
call :TRIM !_tmp! space
echo drive !_drive:~0,1! has !space!GB free space
)
)
)
goto :end
REM :TRIM should get value to trim and a var name to store answer
REM examle: call :TRIM 536870912000 space
REM answer will be 512GB even though correct answer is 500GB
REM cmd.exe cannot handle numbers larger then 32bit
:TRIM
set _tmp=%1
set %2=
set /A %2=!_tmp! >nul 2>nul
if not defined %2 (
set _tmp=!_tmp:~0,-3!
set /A UNIT=!UNIT!+1
call :TRIM !_tmp! %2
goto :eof
)
:GB
if !UNIT! LSS 3 (
set /A %2=!%2!/1024
set /A UNIT=!UNIT!+1
)
if !UNIT! LSS 3 goto :GB
goto :eof
:end

Using set for numeric value (batch)

I am attempting to write a batch program that will monitor cpu usage and stop a virus scan if cpu usage is high. It will then restart the scan when cpu usage drops.
ECHO Checks if the total CPU usage is greater than 10%
SET scanEnd=0
tasklist /FI "IMAGENAME eq scan32.exe" 2>NUL | find /I /N "scan32.exe">NUL
IF "%ERRORLEVEL%"=="0" (
ECHO Program is running
wmic cpu get loadpercentage /value
FOR /f "tokens=2-3 delims==" %%b in ('wmic cpu get loadpercentage /value') do (
echo %%b >> tempfile.txt
echo removed %%a)
SET /a load < tempfile.txt
DEL tempfile.txt
ECHO Load is "%load%"
IF load GEQ 10 (
ECHO High cpu usage
TSKILL scan32
SET scanEnd=1
))
PAUSE
IF "1" == "%scanEnd%" (
ECHO Scan not finished
IF load LSS 10 (
ECHO Restarting scan
"C:\Program Files\McAfee\VirusScan Enterprise\scan32.exe"
SET scanEnd=0))
ECHO End of program
PAUSE
wmic returns the cpu usage in the form LoadPercentage=0 (or other number). I filter this with the for loop and assign the digit to load. For reasons I do not understand, there is something wrong with the assignment. I am unable to echo the value (displays "") and no matter how I define high cpu usage, load passes the IF GEQ statement. Even a 0% load is apparently greater than 10. I know the problem is with set because I checked the tempfile.txt and it is filtered correctly, but I still have no idea why it's wrong.
Thanks for any help.
you assumed that SET command can read from stdin which is not the case.
You might simply assign the FOR variable into a new variable.
Try this
for /f "tokens=2-3 delims==" %%a in ('wmic cpu get loadpercentage /value') do (
set /a load=%%a
)
and then
if %load% geq 10 (
echo load greater than 10%
)
but beware of the assignments inside FOR loops. You may need to enable delayed expansion for them to work correctly, in case there are more than one assignment in the loop. Eventhough this is not your case, you'd just need to adjust
setlocal enabledelayedexpansion
and then refer to it using this optional syntax
if !load! geq 10 (

Resources