8

I am trying to determine if a target pc has atleast 2 GB of free space. Here is what I have so far:

@echo off
for /f "usebackq delims== tokens=2" %%x in (`wmic logicaldisk where "DeviceID='C:'" get FreeSpace /format:value`) do set "FreeSpace=%%x"
IF /i %FreeSpace% GTR "2147483648" (ECHO C Drive Has Enough Available Disk For Install %FreeSpace%) else (ECHO C Drive Is FULL %FreeSpace%)

It does not matter if I set 2 GB or change it to 200 GB it always says I have enough space even though this drive only has 90 GB...Please help if you can.

this question was what I based my above code on: Check free disk space using Batch commands

seems like it should work but it does not.

Sean Beegle
  • 81
  • 1
  • 2

4 Answers4

13

You have 2 problems with your code:

1) IF only does a numeric comparison if the string on both sides evaluates to a number. Your left side is numeric, but your right side has quotes, which forces the entire comparison to be done using string semantics. Numeric digits always sort higher than a quote character, so it always reports TRUE.

As austinian suggests in his answer, removing the quotes apparantly gives the correct answer in your case. But that is not the entire story! In reality it is checking if the free space is greater than or equal to 2147483647.

2) Windows batch (cmd.exe) numbers are limited to signed 32 bit precision, which equates to a max value of 2 GB -1 byte (2147483647). The IF statement has an odd (perhaps unfortunate) behavior that any number greater than 2147483647 is treated as equal to 2147483647. So you cannot use your technique to test free space for values greater than 2147483647.

See https://stackoverflow.com/q/9116365/1012053 for more information.

Described in the link's answer is a tecnique you can use to test large numbers. You must left pad both sides of the condition to the same width, and force a string comparison.

For example, The following will test if free space is >= 4294967296 (4 GB)

@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.
dbenham
  • 641
  • 4
  • 10
  • Sorry this code does not seem to work either. it always reports that 4 GB is available even when run against drives with less than 4 gb free. – Sean Beegle Dec 22 '14 at 13:12
  • @SeanBeegle - Oops, I had the same bug regarding trailing carriage return that austinian had. I was expecting that problem, but somehow fooled myself with my original testing. It should be fixed now. – dbenham Dec 22 '14 at 13:51
  • When I try and change the drive letter from C to D, and run it, I always get an "(echo was unexpected at this time" message, do I have to change anything besides, the DeviceID from C to D? – Sean Beegle Dec 23 '14 at 19:11
  • @SeanBeegle - Yes, you should only have to change the one character. I can't imagine what your problem is. I checked the code against 3 different drives (2 local, 1 network), with different neededSpace values, and always got the correct result. – dbenham Dec 23 '14 at 19:30
  • @dbenham...Thanks for your help!...I realized the error was on my part the machine I was working on did not have a D drive, that was the problem! Thanks again! – Sean Beegle Dec 23 '14 at 21:02
3

Take out the "s from around the number, and the script almost works correctly. Using the "s forces a string comparison instead of a numerical comparison.

As dbenham notes, CMD only stores (and compares) numbers as 32-bit signed ints. Since we're checking for GB, we can reasonably ignore several of less significant digits. If we remove the last 6 digits, then we'll still have MB resolution while being able to detect correctly up to 2 Exabytes of free space. Also, as noted, we have to trim "Number of Digits Removed" + 1 from the WMIC result, due to an extra character at the end.

@ECHO off
SETLOCAL EnableDelayedExpansion
FOR /f "usebackq delims== tokens=2" %%x IN (`wmic logicaldisk where "DeviceID='C:'" get FreeSpace /format:value`) DO SET "FreeSpaceBig=%%x"
SET FreeSpace=!FreeSpaceBig:~0,-7!
IF %FreeSpace% GTR 2147 (ECHO C Drive Has Enough Available Disk For Install %FreeSpace%) else (ECHO C Drive Is FULL %FreeSpace%)
ENDLOCAL

NOTE: you really don't need the /i here either, since it's just for string comparison, and we're doing integer comparison. Also, we could use dir c:\ /-C | find "bytes free" instead of wmic logicaldisk where "DeviceID='C:'" get FreeSpace /format:value, if you want to avoid invoking WMI for this operation (which allows us to omit the EnableDelayedExpansion and use % instead of ! around FreeSpaceBig on line 4. Anyway, it's scripting, there's usually many ways to get the job done.

RELATED:

https://stackoverflow.com/questions/293780/free-space-in-a-cmd-shell https://stackoverflow.com/questions/9099138/save-values-batch-file/9099542#9099542 https://stackoverflow.com/questions/7769918/comparing-2-numbers-in-dos-batch-not-working

austinian
  • 1,699
  • 2
  • 15
  • 29
  • Not quite the whole story. Your answer actually tests if free space is >= 2147483647. See [my answer](http://serverfault.com/a/653810/201695) – dbenham Dec 19 '14 at 21:23
  • @dbenham You know, I thought about that, but completely forgot to consider it again by the time I started writing my answer, unfortunately. I'm going to modify my answer with a loss of precision calculation, as you have a precise calculation in yours. – austinian Dec 19 '14 at 22:17
  • You didn't test! You did not enable delayed expansion, so your substring operation fails. If you do enable delayed expansion, it also gets unexpected result because your value from WMIC has an unwanted carriage return at the end (an artifact of conversion from unicode). So you are only removing last 5 digits, not 6. It works if you switch to normal expansion because that automatically strips carriage returns prior to substring op. Finally, you forgot to adjust your comparison in the last line. You want if > 21474. – dbenham Dec 20 '14 at 03:21
  • I did test, I just got sloppy with my edit wrt the enable delayed expansion, but didn't thoroughly test for values and missed that carriage return issue >.> fixing it now – austinian Dec 22 '14 at 13:30
1

If you just need to check if the drive have enough free space (to install or copy something for example) you can try wmic query like this:

wmic LogicalDisk where "DeviceID='c:' and FreeSpace > 10737418240" get DeviceID 2>&1 ^ | find /i "c:" >nul || (echo not enough space&exit 1)

this will break batch file execution if there is less than 10Gb free on C:

anilech
  • 113
  • 5
-2

Here's a different way of going about it... but it is not very precise.

This method uses string length operations against the "number of bytes free" listed under dir and the drive properties.

for /f "tokens=3" %%a in ('dir T:\') do (
 set bytesfree=%%a
)
ECHO %bytesfree%>x&FOR %%? IN (x) DO SET /A strlen=%%~z? - 2&del x
IF %strlen% LEQ 13 (

)

The specific example above determines if there is less than 10GB of free space on the T drive.

I just wanted to share this unorthodox way of going about it for those who don't like a lot of code.

Aaron Gillion
  • 107
  • 1
  • 5