我正在尝试使用批处理文件获取免费的硬盘空间。它以字节为单位返回空格,但我需要它以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。
我还有其他办法吗?
答案 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)
您可以使用wmic
或fsutil
获取驱动器/卷上的可用空间。我的示例使用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