2013-11-26 50 views
0

我想使用批處理文件來獲得可用的硬盤空間。它以字節返回空間,但我需要它在GB中。 我試過轉換,但批處理中有一些限制,不允許在很大數量的操作。如何使用批處理文件獲取可用硬盤空間?

這是我的腳本。

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

我也嘗試消除最後9位數字(GB),但它是非常不準確的。例如。如果可用空間是180 GB,則顯示200GB。

有沒有其他辦法可以做到這一點?

回答

0

好吧 - 讓我們這樣說吧。你已經選擇把所有的蟲子都放回罐子裏,好嗎?

在商業上,製造商更願意以千兆字節來表示大小 - 他們調用SI(Systeme Internationale)的權限並使用10 ** 9的因子。

計算機工業使用2的權力,所以SI引入了衆所周知的術語Gigibyte(或者說我可靠地被告知),這意味着2 ** 30。

(SI也想你指的「10公斤」或「10米」,而不是「10公斤」或「10儀表」啊 - 。一個指令認真遵循只術語火雞)

所以 - 因爲這個數字更大,因此比業界使用的GigIbytes更好。

所有這些當然都不在經驗和理解Longlegs小姐這位老闆的細枝末節,她會毫不猶豫地告訴你她有200Gb,而不是180--所以你是RONG!

儘管使用字節邏輯是合理的,但您確實在推動讓公司外部的自我聲明的「專家」理解 - 甚至大多數內部人員不知道「官方」術語。他們的口頭說話讓聽衆不知所措,而且你是在寫它,所以很少有人知道正確的術語(但很多人相信他們知道),你可以簡單地將其視爲POR SPELA

但是 - 如果你真的想用2 ** 30的定義:

批是指不限2 ** 31,所以你必須要麼使用另一種工具(可能來自一批調用,使它的行爲),或者如果你堅持保持純粹的批處理,通過使用長分法方法手動設計一個子串重複減法方法來執行你的除法。

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)

+0

+1,***非常好!我一直想用自定義的WMIC格式來欺騙,但從來沒有勇氣。現在我已經看到了你的成功,有一天我可能會刺傷它:-) – dbenham

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 
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 
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