如何使用批处理文件获得免费的硬盘空间?

时间:2013-11-26 08:12:51

标签: batch-file

我正在尝试使用批处理文件获取免费的硬盘空间。它以字节为单位返回空格,但我需要它以GB为单位。 我尝试过转换,但批量中有一些限制,不允许对非常大的数量进行操作。

这是我的剧本。

for /f "tokens=2" %%S in ('wmic volume get DriveLetter^, FreeSpace ^| findstr "^C:"') do set freeSpace=%%S
echo %freeSpace%

我也试图消除最后9位数(GB),但这是非常不准确的。例如。如果可用空间为180 GB,则显示为200 GB。

我还有其他办法吗?

5 个答案:

答案 0 :(得分:3)

只是为了好玩/学习。

在Windows中,%windir%\system32\wbem文件夹包含用于wmic输出格式的xsl文件。 wmic允许您指示xsl文件(/format参数)。所以,我从wbem文件夹中复制了textvaluelist.xsl文件,并将其更改为获得所需内容。

最后,我生成了这个myFormat.xsl文件:

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output encoding="utf-16" omit-xml-declaration ="yes"/>
<xsl:template match="/" xml:space="preserve"><xsl:apply-templates select="//INSTANCE"/></xsl:template>
<xsl:template match="INSTANCE" xml:space="preserve"><xsl:apply-templates select="PROPERTY|PROPERTY.ARRAY|PROPERTY.REFERENCE"/></xsl:template>
<xsl:template match="PROPERTY" xml:space="preserve"><xsl:value-of select="@NAME"/>=<xsl:apply-templates select="VALUE"><xsl:with-param name="type"><xsl:value-of select="@TYPE"/></xsl:with-param><xsl:with-param name="name"><xsl:value-of select="@NAME"/></xsl:with-param></xsl:apply-templates>
</xsl:template>
<xsl:template match="PROPERTY.ARRAY" xml:space="preserve"><xsl:value-of select="@NAME"/>=<xsl:apply-templates select="VALUE.ARRAY"><xsl:with-param name="includequotes">true</xsl:with-param><xsl:with-param name="type"><xsl:value-of select="@TYPE"/></xsl:with-param></xsl:apply-templates></xsl:template>
<xsl:template match="PROPERTY.REFERENCE" xml:space="preserve"><xsl:value-of select="@NAME"/>=<xsl:apply-templates select="VALUE.REFERENCE"></xsl:apply-templates></xsl:template>
<xsl:template match="VALUE.REFERENCE">"<xsl:apply-templates select="INSTANCEPATH/NAMESPACEPATH"/><xsl:apply-templates select="INSTANCEPATH/INSTANCENAME|INSTANCENAME"/>"</xsl:template>
<xsl:template match="NAMESPACEPATH">\\<xsl:value-of select="HOST/text()"/><xsl:for-each select="LOCALNAMESPACEPATH/NAMESPACE">\<xsl:value-of select="@NAME"/></xsl:for-each>:</xsl:template>
<xsl:template match="INSTANCENAME"><xsl:value-of select="@CLASSNAME"/><xsl:for-each select="KEYBINDING"><xsl:if test="position()=1">.</xsl:if><xsl:value-of select="@NAME"/>="<xsl:value-of select="KEYVALUE/text()"/>"<xsl:if test="position()!=last()">,</xsl:if></xsl:for-each></xsl:template>
<xsl:template match="VALUE.ARRAY"><xsl:param name="type"/>{<xsl:for-each select="VALUE">
        <xsl:apply-templates select=".">
            <xsl:with-param name="type">
                <xsl:value-of select="$type"/>
            </xsl:with-param>
            <xsl:with-param name="includequotes">true</xsl:with-param>
        </xsl:apply-templates>
        <xsl:if test="position()!=last()">,</xsl:if>
</xsl:for-each>}</xsl:template>
<xsl:template match="VALUE">
    <xsl:param name="type"/>
    <xsl:param name="name"/>
    <xsl:param name="includequotes"/>
    <xsl:choose>
        <xsl:when test="$type='string'">
            <xsl:if test="$includequotes='true'">"</xsl:if><xsl:value-of select="."/><xsl:if test="$includequotes='true'">"</xsl:if>
        </xsl:when>
        <xsl:when test="$type='char16'">
            '<xsl:value-of select="."/>'
        </xsl:when>
        <xsl:when test="$type='uint64' and $name='FreeSpace'">
            <xsl:value-of select="format-number(. div 1073741824,'#0.00')"/>GB
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="."/>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>
</xsl:stylesheet>

对微软的原始版本进行少量修改。最后,有一个修改来处理FreeSpace属性的情况,返回它转换为GB。

现在,要使用它,

wmic volume where "driveLetter='c:'" get capacity,freespace /format:"c:\pathTo\myFormat.xsl"

生成

Capacity=241173401600
FreeSpace=153.61GB

正如您所看到的,由于该规则仅包含在FreeSpace属性中,因此仅转换它,而Capacity则不转换。

我知道,对于一个简单的任务来说很复杂,但正如所说,只是为了好玩(第一次编辑xsl)

答案 1 :(得分:0)

嗯 - 让我们这样说吧。你选择自己把所有的蠕虫放回罐子里,好吗?

在商业上,制造商更愿意以千兆字节表示大小 - 他们为此调用SI(Systeme Internationale)的权限并使用10 ** 9的因子。

计算机行业使用2的幂,因此SI引入了众所周知的术语Gigibyte(或者我得到了可靠的通知),这意味着2 ** 30.

(SI也希望你提到“10公斤”或“10米”,而不是“10公斤”或“10米”。是的 - 只有火鸡术语刻苦追求的指示)

所以 - GigAbytes适用于制造商,因为数量更大,因此优于业内使用的GigIbytes数字。

所有这一切当然超出了老板的秘密长老小姐的经验和理解,她将毫不含糊地告诉你她有200Gb,而不是180-所以你是RONG!

尽管使用Gig i 字节是合乎逻辑的,但你真的在推动众所周知的让IT之外的自称“专家”理解 - 甚至大多数内部人都不知道“官方“术语。他们的用法使听觉变得与众不同,你是不是在写它,所以很少有人知道正确的术语(但是很多人确信他们 意识到)你只会被视为 POR SPELA

但是 - 如果你真的,真的想要使用2 ** 30定义:

批次限制为2 ** 31,因此您必须使用其他工具(可能从批处理中调用以使其表现)或者如果您坚持保留纯批次,请通过手动设计子字符串来执行划分 - 和重复减法方法,采用长除法。

答案 2 :(得分:0)

以下是解决这些限制的几种方法。

@echo off
setlocal enabledelayedexpansion

set wmi=WMIC LogicalDisk Where DriveType='3' Get DeviceID,FreeSpace,Size^|Find ":"
for /f "tokens=1,3,4" %%a in ('"%wmi%"') do (
   call :GetUnit %%b ufree
   call :Convertbytes %%b !ufree! free
   call :GetUnit %%c usize
   call :Convertbytes %%c !usize! size
   Echo %%a Free space: !free! !ufree! of !size! !usize!
)

exit /b

:ConvertBytes bytes unit ret
setlocal
if "%~2" EQU "KB" set val=/1024
if "%~2" EQU "MB" set val=/1024/1024
if "%~2" EQU "GB" set val=/1024/1024/1024
if "%~2" EQU "TB" set val=/1024/1024/1024/1024
> %temp%\tmp.vbs echo wsh.echo FormatNumber(eval(%~1%val%),0)
for /f "delims=" %%a in ( 
  'cscript //nologo %temp%\tmp.vbs' 
) do endlocal & set %~3=%%a
del %temp%\tmp.vbs
exit /b

:GetUnit bytes return
set byt=00000000000%1X
set TB=000000000001099511627776X
if %1 LEQ 1024 set "unit=Bytes"
if %1 GTR 1024   set "unit=KB"
if %1 GTR 1048576  set "unit=MB"
if %1 GTR 1073741824  set "unit=GB"
if %byt:~-14% GTR %TB:~-14% set "unit=TB"
endlocal & set %~2=%unit%
exit /b

答案 3 :(得分:0)

您可以使用wmicfsutil获取驱动器/卷上的可用空间。我的示例使用fsutil。您可以在命令提示符下执行64位数学运算,但它有点复杂。因此,我们将cscript通过VBS文件( eval.vbs )处理该部分(包括舍入),其中包含一个代码行:

WScript.Echo Round(Eval(WScript.Arguments(0)), WScript.Arguments(1))

此批处理文件获取可用空间,将其传递给VBS脚本并将可用空间回显到控制台。如果希望VBS脚本简单地将所有内容回显到控制台,则可以消除第二个for语句,但是VBS脚本不能用于其他目的。

@echo off

setlocal ENABLEDELAYEDEXPANSION

for /f "tokens=2 delims=:" %%i in ('fsutil volume diskfree c: ^| find /i "of free"') do set _free=%%i
for /f %%i in ('cscript //nologo eval.vbs "!_free!/1024/1024/1024" 2') do set _free=%%i
echo The C: drive has !_free! GB free

endlocal

在我的电脑上返回以下内容:

The C: drive has 45.26 GB free

答案 4 :(得分:0)

刚刚完成。而作为另一个答案,只是为了好玩。孩子们,这不应该这样做。没有错误检查,只是概念:将较大的存储值(以字节为单位)减少到较小的存储单元。

@echo off

    call :reduceStorage 241173401600  value
    echo %value%

    call :reduceStorage 1024 value
    echo %value%

    exit /b

rem --------------------------------------------------------------------
rem Reduce input number by dividing it by 1024 as many times as needed

:reduceStorage size resultVar
    setlocal
    set "size=%~1"
    set "u="
    for %%u in (K M G T P E Z Y) do if not "!size:~5,1!"=="" (
            call :divide "!size!" 1024 size
            set "u=%%u"
    )
    endlocal & set "%~2=%size% %u%B"
    goto :EOF

rem --------------------------------------------------------------------
rem Divide a large number by a small (2E31) number
:divide number div resultVar
    setlocal
    set "num=%~1"
    set "d=%~2"
    set "a="
    call :length "%num%" len
    for /l %%l in (0 1 %len%) do (
        if defined num (
            set "a=!a!!num:~0,1!"
            set "num=!num:~1!"
            if !a! lss %d% (
                if defined res set "res=!res!0"
            ) else (
                set /a "r=!a!/%d%"
                set "res=!res!!r!"
                set /a "b=!a!-(%d%*!r!)"
                if !b! gtr 0 (
                    set "a=!b!"
                ) else (
                    set "a="
                )
            )
        )
    )

    endlocal & set "%~3=%res%"
    goto :EOF

rem --------------------------------------------------------------------
rem return the length in characters of a variable
:length string returnValue
    setlocal enableextensions enabledelayedexpansion
    set "p=16384"
    set "s=%~1"
    for %%i in ( 8192 4096 2048 1024 512 256 128 64 32 16 8 4 2 1 ) do (
        for %%j in (!p!) do if "!s:~%%j,1!"=="" ( set /a "p-=%%i" ) else ( set /a "p+=%%i" )
    )
    if not "!string:~%p%,1!"=="" set /a p+=1
    endlocal & set "%~2=%p%"
    goto :EOF