Batch file to evaluate the free space of my local drive? - windows

I'm looking for a batch file to evaluate the free space of my local drive.
For example I want to code a batch file to know whether the free space is greater than 300 GB or not. So I found out my free space is 45 GB using
wmic LOGICALDISK where drivetype=3 get caption,size,FreeSpace
But when I compare it with 300 GB, it shows that 45 is greater than 300.
Apparently this batch file program calculates it as a string?
Please help me find a solution. Thanks in advance.

The simplest way is to incorporate the 300 GiB, (322122547200 bytes), size as a query filter:
WMIC LogicalDisk Where "DriveType='3' And FreeSpace>'322122547200'" Get Caption,Size,FreeSpace
Note: You may additionally wish to use the following instead:
300000000000 (300 GB to bytes)

Related

Using Windows Command Prompt (or PowerShell) to get Disk Drives Listed by Media Type and abbreviated size (GB/TB) as simply as possible

I'm hoping to find a solution that doesn't require a large block of text / code, hopefully only 1 or 2 lines in a .bat script.
So far the main PowerShell call that does these 2 things is the Get-PhysicalDisk, MediaType and Size,
But Size doesn't automatically abbreviate to GB / TB, but I know it or Format Table can, because it does abbreviate to GB / TB if the column it is listed in is restricted in size (width), but I can't figure out a way to force it to?
The standard entry I've used from command prompt is:
PowerShell "Get-PhysicalDisk | FT -AutoSize"
Which gives me something like:
Output on Command-Line
Which looks perfectly fine so long as your HDD / SDDs don't have some insanely long Serial #. In which case you don't even get to see the size. But the real issue is if you want to customize this so you always see the Size ie: PowerShell "Get-PhysicalDisk | FT Size, MediaType, FriendlyName, HealthStatus, OperationalStatus -hideTableHeaders -auto"
Now the size doesn't get summarized in GB, it gets the full number treatment like so:
Output on Command-Line
So is there a way to format or adjust this simply so it'll list in GB, while also having a listed Media Type? (forgot to add that in the end reminder) and if it has to be with a script does anyone have a succinct one?
~TY in advance!
An additional Q, using PowerShell "Get-Disk | FT -auto"
I get a good abbrev in GB as well, but can't |FT the "Total Size" since it has a space in it? or is there a trick to that?
Output on Command-Line
Apply Using PowerShell's Calculated Properties article e.g. as follows:
Get-PhysicalDisk |
Format-Table -Property #{Name='Size GB'; Expression={$_.Size / 1GB}},
MediaType, FriendlyName, HealthStatus, OperationalStatus -AutoSize

winapi to retrieve the maximum configured page file size for all drives

It appears that both GlobalMemoryStatusEx and GetPerformanceInfo Windows APIs report the current size of the page file, but the page file can be configured (per disk) to grow up to a certain limit.
Is there an API to retrieve that limit, so that I can calculate the maximum possible commit size for the whole system (provided page file settings otherwise remain unchanged)?
Seems to be possible via WMI (COM and/or command-line):
wmic pagefile list /format:list
wmic pagefileset list /format:list
But can also be done in a platform-dependent* way by reading/parsing this registry setting:
HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management\PagingFiles
As described here, this format is REG_MULTI_SZ (one line per page file):
<page-file> [<initial-size> <max-size>]
For example:
c:\pagefile.sys 1024 8192
In case of a system-managed page file the value would be:
?:\pagefile.sys
In case of system-managed the size is limited by the free space on the system drive (not entirely true for Hyper-V VMs).
* The registry setting appears to work at least in Windows XP, 7, 2012 and 10 (32/64-bit, PC).

Why is my IF comparison op failing?

update SOLVED - the problem is not with my code. there is a design limitation (some might say "bug") in the command processor. the IF comparison operators do not work with values higher than 2147483648. now I just have to figure out how to strip off some of the least significant digits for the workaround. thanks to all for reading.
=======
hello out there in cyberland,
I manage a small company's network. I'm trying to set up an automated archival process using a batch file running on a server, and need a little help with the logic. I'm not a programmer and don't have the time to learn PowerShell or VBscript. I have read and re-read the MS command reference on IF, FOR, and CALL, and can not figure out what I'm doing wrong.
We have a Windows 2000 Server with two disk drives and a tape drive. One disk has a shared folder, call it Public; the other disk is not shared, call it Staging.
The Public drive will accept incoming backups from the client desktops. I need the process to move files from the Public drive to the Staging drive until the drive is too full to accept any more files, whereupon the tape backup starts. Upon completion of the tape run, the Staging drive will be emptied and the process will resume moving files from Public to Staging.
The goal is to automatically and perpetually archive the desktop backup files to tape, with no user intervention other than changing the tape.
You may ask, why involve two drives? Two reasons:
1) If the desktops back up directly to the Staging drive, at some point the client desktop backups will fail for lack of space on the target drive. I have no way to predict when this will occur; the only definable condition I can think of would be an arbitrary threshold of free disk space, but since the backup files to be archived will be different sizes, I could run into a situation where the target drive free space is above the threshold, but the next backup exceeds that space. Result: client desktop backup fails and server tape backup does not start.
2) If the Staging drive fills up and the tape backup fails for some reason (tape not changed or whatever), having the desktops back up to the Public drive buys me some time to fix the tape issue before the desktop backups begin to fail.
Here is the algorithm I'm trying to code:
1) Begin
2) Obtain free space on Staging drive
3) Obtain size of smallest file on Public drive (if no files present, exit)
4) Compare file size with free space on Staging drive
5) if file will fit, move it to Staging drive; else, exit and start Tape Backup
6) return to Begin
And here is my batch code which is not working. At this stage in testing, I have one file (8 GB) in the Public drive which will fit in the free space (32 GB) on the Staging drive. The set command confirms the variables are being set as expected; the process is failing at the statement [ if %BKFsize% LSS %DiskFree%" ]. Instead of the file being moved, the tape routine specified by 'else' is called instead:
#echo off
setlocal enableextensions enabledelayedexpansion
:Begin
REM obtain and display free space on Staging drive.
D:
for /f "tokens=3 delims= " %%A in ('dir ^| find "bytes free"') do (
set Z=%%A
set Z=!Z:,=!
)
set DiskFree=!Z!
echo.
echo D: has %DiskFree% bytes free
echo.
REM obtain sizes of files on Public drive to be moved.
E:
cd \backup.email
if not exist *.bkf exit
dir *.bkf /b /os > BKFlist.txt
for /f "tokens=*" %%G in (BKFlist.txt) do call :CheckBKF "%%G"
goto :eof
:CheckBKF
set BKFfile=%1
set BKFsize=%~z1
echo.
echo File %BKFfile% is %BKFsize% bytes
echo.
set
pause
REM move file(s) to Staging drive, space permitting; or,
REM if not enough space for smallest file, start tape backup.
if %BKFsize% LSS %DiskFree% (
echo Moving file %BKFfile% to drive D
echo.
move E:\backup.email\%BKFfile% D:\backup.email
) else (
C:\WINNT\AutoBackup\TapeBKF.cmd
exit
)
goto Begin
:End
I know this must be fairly simple but like I said, I'm not a programmer, and I bow to your superior skill. Any advice is much appreciated, and thank you.
In batch file, there is no real difference between strings and integers types, but that isn't your problem here.
The problem is that integers only works in the 32 bit signed range.
-2147483648 to 2147483647
But your filesize is greater and also your disk space.
To test this you could try to add a one.
Set /a myvar=BKFsize+1
Set /a myvar=DiskFree+1
I suppose you get an error.
You could solve it, if you try to use the string compare, currently you do a string compare but your numbers are not of the same length, so you get "unpredictable" results.
But if you adjust/filling the strings with zeros so they have the same length, it should work.
set "strBKSize=000000000000000000%bkSize%"
set "strBKSize=%strBKSize:~-15%"
set "strDisksize=000000000000000000%Disksize%"
set "strDisksize=%strDisksize:~-15%"
Or you try to calculate not with bytes, but in MB or GB, by removing 6 or 9 numbers/characters.
set BKFsizeGB=%BKFsize:~0,-9%
Then you can use them as numbers.
Maybe the values contained in your variables are not integers but strings
I suppose it's comparing: 8<3 == false

Maximum number of drives in windows?

I'm trying to figure out the available disk space programmatically in windows. For this, I need to first get a list of the available drives, then check which of those are local drives and then query the available bytes on each local drive.
I'm a bit stuck on the first part, where the API presents two functions:
GetLogicalDrives (http://msdn.microsoft.com/en-us/library/aa364972(VS.85).aspx) which gives you a DWORD with the bits set (bit 0 if drive A is present, bit 1 if drive B etc)
GetLogicalDriveStrings (http://msdn.microsoft.com/en-us/library/aa364975(VS.85).aspx) which gives you the actual strings.
Now, although I'll be using strings later on, I'd prefer using the first option for querying. However, on my system a DWORD is typedef-ed to "unsigned long", which is 4 bytes, whereas drive letters only range A-Z (26 - i think - characters). Obviously, one can define more than 26 drives on their system (however unlikely they are to do so) - so I was wondering if there was any convention for those drives. Can someone point me to a resource on this?
Thanks.
DWORD is always 4 bytes, regardless of the system (it's a Win32 type).
The maximum for drive letters in Windows is 26. Because English alphabet has only 26 letters :). However, Windows allows two ways to mount a volume:
to a drive letter
to a directory (on an NTFS volume).
You can mount one volume to multiple locations (but no more than one drive letter, IIRC). A GUI for this task is presented by Control Panel -> Administrative Tools -> Computer Management -> Disk Management.
If you want to have more than 26 drives with the additional drives being redirects to already active drives and are okay with them not working properly in most programs, then you can assign more with the following method (be warned they won't even show up in the file explorer):
subst ♪: C:\Temp\
cd /D ♪:\
and to delete them (also they aren't preserved through restarts):
subst /D ♪:
You can enumerate all volumes and their mount points as described in this article.
You could use WMI. The following WMI query should list all drives:
SELECT * FROM Win32_DiskDrive
It it not sufficient to enumerate MS-DOS drives (there can be at most 26 of them, by the way, although each can be bound twice, once globally and once locally in your session), a volume can, for example, be mounted to a directory. What you want is probably to enumerate all volumes in the system, using FindFirstVolume et al. Take a look at the associated MSDN example.

How can I view the allocation unit size of a NTFS partition in Vista?

Which built in (if any) tool can I use to determine the allocation unit size of a certain NTFS partition ?
Open an administrator command prompt, and do this command:
fsutil fsinfo ntfsinfo [your drive]
The Bytes Per Cluster is the equivalent of the allocation unit.
Use diskpart.exe.
Once you are in diskpart select volume <VolumeNumber> then type filesystems.
It should tell you the file system type and the allocation unit size. It will also tell you the supported sizes etc. Previously mentioned fsutil does work, but answer isn't as clear and I couldn't find a syntax to get the same information for a junction point.
I know this is an old thread, but there's a newer way then having to use fsutil or diskpart.
Run this powershell command.
Get-Volume | Format-List AllocationUnitSize, FileSystemLabel
Another way to find it quickly via the GUI on any windows system:
create a text file, type a word or two (or random text) in it, and save it.
Right-click on the file to show Properties.
"Size on disk" = allocation unit.
The value for BYTES PER CLUSTER - 65536 = 64K
C:\temp>fsutil fsinfo drives
Drives: C:\ D:\ E:\ F:\ G:\ I:\ J:\ N:\ O:\ P:\ S:\
C:\temp>fsutil fsinfo ntfsInfo N:
NTFS Volume Serial Number : 0xfe5a90935a9049f3
NTFS Version : 3.1
LFS Version : 2.0
Number Sectors : 0x00000002e15befff
Total Clusters : 0x000000005c2b7dff
Free Clusters : 0x000000005c2a15f0
Total Reserved : 0x0000000000000000
Bytes Per Sector : 512
Bytes Per Physical Sector : 512
Bytes Per Cluster : 4096
Bytes Per FileRecord Segment : 1024
Clusters Per FileRecord Segment : 0
Mft Valid Data Length : 0x0000000000040000
Mft Start Lcn : 0x00000000000c0000
Mft2 Start Lcn : 0x0000000000000002
Mft Zone Start : 0x00000000000c0000
Mft Zone End : 0x00000000000cc820
Resource Manager Identifier : 560F51B2-CEFA-11E5-80C9-98BE94F91273
C:\temp>fsutil fsinfo ntfsInfo N:
NTFS Volume Serial Number : 0x36acd4b1acd46d3d
NTFS Version : 3.1
LFS Version : 2.0
Number Sectors : 0x00000002e15befff
Total Clusters : 0x0000000005c2b7df
Free Clusters : 0x0000000005c2ac28
Total Reserved : 0x0000000000000000
Bytes Per Sector : 512
Bytes Per Physical Sector : 512
Bytes Per Cluster : 65536
Bytes Per FileRecord Segment : 1024
Clusters Per FileRecord Segment : 0
Mft Valid Data Length : 0x0000000000010000
Mft Start Lcn : 0x000000000000c000
Mft2 Start Lcn : 0x0000000000000001
Mft Zone Start : 0x000000000000c000
Mft Zone End : 0x000000000000cca0
Resource Manager Identifier : 560F51C3-CEFA-11E5-80C9-98BE94F91273
Easiest way, confirmed on 2012r2.
Go to "This PC"
Right click on the Disk
Click on Format
Under drop down "allocation unit size" will be the value of what the Allocation of the Unit size disk already is.
In a CMD (as adminstrator), first run diskpart. In the opened program, enter list disk. It'll list all connected disks.
Select the right disk based on its size. If it is flash memory, usually it'd be the last item in the list. In my case, I select the Disk 2 using this command: select disk 2.
After selecting your disk, list the partitions using list partion command. You'll get a list like the one in the image below.
Now, it is time to select the right partition, based on its size. In my case, I select Partition 1 using this command: select partition 1.
Finally, you can run the filesystem command to get the Allocation Unit Size.
Note: This procedure works on both NTFS and FAT32.
According to Microsoft, the allocation unit size "Specifies the cluster size for the file system" - so it is the value shown for "Bytes Per Cluster" as shown in:
fsutil fsinfo ntfsinfo C:
You can use SysInternals NTFSInfo by Mark Russinovich from the command line and it converts fsutil fsinfo ntfsinfo into more readable information, especially MFT Table info.
The simple GUI way, as provided by J Y in a previous answer:
Create a small file (not empty)
Right-click, choose Properties
Check "Size on disk" (in tab General), double-check that your file size is less than half that so that it is certainly using a single allocation unit.
This works well and reminds you of the significance of allocation unit size. But it does have a caveat: as seen in comments to previous answer, Windows will sometimes show "Size on disk" as 0 for a very small file. In my testing, NTFS filesystems with allocation unit size 4096 bytes required the file to be 800 bytes to consistently avoid this issue. On FAT32 file systems this issue seems nonexistent, even a single byte file will work - just not empty.
from the commandline:
chkdsk l: (wait for the scan to finish)
sizdir32 http://www.ltr-data.se/opencode.html/
start > run > MSINFO32
goto components
goto storage
goto disk
on the right look for Bytes/Sector

Resources