Get size of a directory in 'MB' using batch file

后端 未结 4 1483

I want to get the size of directory say C:\\Temp in MB using batch file. I don\'t need sizes of child directories or files, but the size of directo

相关标签:
4条回答
  • 2020-11-27 08:26
    @echo off
    ::robocopy "%~1" %TEMP% /S /L /BYTES /XJ /NFL /NDL /NJH
    for /f "tokens=2 delims=: " %%a in ('
        robocopy "%~1" %TEMP% /S /L /BYTES /XJ /NFL /NDL /NJH ^| find "Bytes"
    ') do set "bytes=%%a"
    
    
    ::1048576
    
    set "beginJS=mshta "javascript:close(new ActiveXObject('Scripting.FileSystemObject').GetStandardStream(1).Write("
    set "endJS=));""
    
    
    
    
    for /f %%N in (
      '%beginJS% %bytes%/1048576 %endJS%'
    ) do set mb=%%N
    echo mb=%mb%
    

    It takes one argument - the folder which size you want to calculate

    0 讨论(0)
  • 2020-11-27 08:33

    Here is a pure batch file solution (refer to the remarks in the code for some brief explanations):

    @echo off
    setlocal EnableExtensions DisableDelayedExpansion
    
    rem Define constants here:
    set /A DIVISOR=1024 & rem (1024 Bytes = 1 KBytes, 1024 KBytes = 1 MByte,...)
    set "ROUNDUP=#" & rem (set to non-empty value to round up results)
    
    rem Get size of directory given as command line argument:
    for /F "tokens=2 delims=: " %%B in ('
        robocopy "%~1" "%~1" "*.*" /L /S /XJ /BYTES /NP /NFL /NDL /NJH ^| ^
            find /I "Bytes"
    ') do set "BYTES=%%B"
    if not defined BYTES set "BYTES=0"
    rem Display result in Bytes and divide it to get KBytes, MBytes, etc.:
    call :DIVIDE %BYTES% 1 RESULT
    echo( Bytes:    %RESULT%
    call :DIVIDE %RESULT% %DIVISOR% RESULT REST
    if defined ROUNDUP if 0%REST% GTR 0 set /A RESULT+=1
    echo(KBytes:    %RESULT%
    call :DIVIDE %RESULT% %DIVISOR% RESULT REST
    if defined ROUNDUP if 0%REST% GTR 0 set /A RESULT+=1
    echo(MBytes:    %RESULT%
    call :DIVIDE %RESULT% %DIVISOR% RESULT REST
    if defined ROUNDUP if 0%REST% GTR 0 set /A RESULT+=1
    echo(GBytes:    %RESULT%
    
    endlocal
    exit /B
    
    
    :DIVIDE val_dividend val_divisor [ref_result] [ref_remainder]
    rem Divide a huge number exceeding the 32-bit limitation
    rem by a 32-bit number in the range from 1 to 1000000000;
    rem the result might also exceed the 32-bit limitation.
    setlocal EnableDelayedExpansion
    set "DIVIDEND=%~1"
    set "DIVISOR=%~2"
    set "QUOTIENT=%~3"
    set "REMAINDER=%~4"
    
    rem Check whether dividend and divisor are given:
    if not defined DIVIDEND (
        >&2 echo(Too few arguments, dividend missing^^!
        exit /B 2
    ) else if not defined DIVISOR (
        >&2 echo(Too few arguments, divisor missing^^!
        exit /B 2
    )
    rem Check whether dividend is purely numeric:
    for /F "tokens=* delims=0123456789" %%N in ("!DIVIDEND!") do (
        if not "%%N"=="" (
            >&2 echo(Dividend must be numeric^^!
            exit /B 2
        )
    )
    rem Convert divisor to numeric value without leading zeros:
    for /F "tokens=* delims=0" %%N in ("%DIVISOR%") do set "DIVISOR=%%N"
    set /A DIVISOR+=0
    rem Check divisor against its range:
    if %DIVISOR% LEQ 0 (
        >&2 echo(Divisor value must be positive^^!
        exit /B 1
    ) else if %DIVISOR% GTR 1000000000 (
        >&2 echo(Divisor value exceeds its limit^^!
        exit /B 1
    )
    set "COLL=" & set "NEXT=" & set /A INDEX=0
    rem Do a division digit by digit as one would do it on paper:
    :LOOP
    if "!DIVIDEND:~%INDEX%,1!"=="" goto :CONT
    set "NEXT=!NEXT!!DIVIDEND:~%INDEX%,1!"
    rem Remove trailing zeros as such denote octal numbers:
    for /F "tokens=* delims=0" %%N in ("!NEXT!") do set "NEXT=%%N"
    set /A NEXT+=0
    set /A PART=NEXT/DIVISOR
    set "COLL=!COLL!!PART!"
    set /A NEXT-=PART*DIVISOR
    set /A INDEX+=1
    goto :LOOP
    :CONT
    rem Remove trailing zeros as such denote octal numbers:
    for /F "tokens=* delims=0" %%N in ("%COLL%") do set "COLL=%%N"
    if not defined COLL set "COLL=0"
    rem Set return variables or display result if none are given:
    if defined QUOTIENT (
        if defined REMAINDER (
            endlocal
            set "%REMAINDER%=%NEXT%"
        ) else (
            endlocal
        )
        set "%QUOTIENT%=%COLL%"
    ) else (
        endlocal
        echo(%COLL%
    )
    exit /B
    

    Basically, the size of the contents of the directory given as command line argument is gathered by robocopy, similar to npocmaka's approach; the resulting size in Bytes is stored in variable BYTES.

    Afterwards, several subroutine calls are done, each to divide the result by 1024 in order to get the size in KBytes, then MBytes and GBytes.

    The values resulting from the divisions are incremented by 1 if there is a remainder in order to round up the sizes (similar to Windows Explorer, which for example displays 1 KB for very small files). You can disable this feature by setting variable ROUNDUP to an empty string, which leads to rounding down.


    Division Approach

    Since the set /A command (and its division operator /) can handle (signed) 32-bit integers only, the subroutine :DIVIDE performs the actual division like one would do it on paper. The dividend (that is the number to be divided) is treated as a string, so the 32-bit range can be exceeded; the divisor (that is the number to divide by) however must not exceed it; rather it must be in the range from 1 to 1000000000. The loop at :LOOP consisting of goto :LOOP and a conditional goto :CONT constitutes a while-loop-like structure that iterates through all the decimal figures of the dividend and terminates after the last one has been reached.

    The subroutine expects at least two arguments -- the values of the dividend and the divisor. It accepts even two more -- the name of a variable to hold the quotient (that is the division result) and another one to hold the remainder. If no optional arguments are given, the quotient is displayed on the console.

    0 讨论(0)
  • 2020-11-27 08:39

    if you need exact values, go for another option. But if you need a rough value only (cut, not rounded, not 1024 as divisor but 1000 only):

    @echo off
    for /f "tokens=2 delims=," %%a in ('dir *^|findstr /e "Bytes"') do (
      for /f "delims= " %%i in ("%%a") do set size=%%i
    )
    echo size in Bytes: %size%
    echo that's about %size:~0,-4% KB
    echo or about %size:~0,-8% MB
    echo or about %size:~0,-12% GB
    

    Advantage: this is string manipulation only, no math included, so it even works outside 32bit Integer (which would be limited to sizes up to about 2GB).

    0 讨论(0)
  • 2020-11-27 08:42

    You can do it with a hybrid script [Batch/Vbscript] like this one :

    @echo off
    set Folder="C:\temp"
    echo The size of %Folder% is 
    Call :GetSize %Folder%
    pause
    :GetSize
    (
    echo wscript.echo GetSize("%~1"^)
    echo Function GetSize(MyFolder^)
    echo    Set fso = CreateObject("Scripting.FileSystemObject"^)
    echo    Set objFolder= fso.GetFolder(MyFolder^)  
    echo    GetSize = FormatSize(objFolder.Size^)
    echo End Function
    echo '*******************************************************************
    echo 'Function to format a number into typical size scales
    echo Function FormatSize(iSize^)
    echo    aLabel = Array("bytes", "KB", "MB", "GB", "TB"^)
    echo    For i = 0 to 4
    echo        If iSize ^> 1024 Then
    echo            iSize = iSize / 1024
    echo        Else
    echo            Exit For
    echo        End If
    echo    Next
    echo    FormatSize = Round(iSize,2^) ^& " " ^& aLabel(i^)
    echo End Function
    echo '*******************************************************************
    )>%tmp%\Size.vbs
    Cscript /NoLogo %tmp%\Size.vbs
    Del %tmp%\Size.vbs
    Exit /b
    

    Edit : on 30/03/2016 @12:11

    And this a nice trick

    the Liviu's hack for embedding vbscode in batch without temp files

    I just discovered from npocmaka thanks to him

    @echo off
    Set Folder="c:\temp"
    @cScript.EXE //noLogo "%~f0?.WSF" %Folder%  //job:info %~nx0%*
    pause
    @exit /b 0
    <job id="info">
    <script language="VBScript">
    wscript.echo GetSize(WScript.Arguments(0))
    Function GetSize(MyFolder)
        Set fso = CreateObject("Scripting.FileSystemObject")
        Set objFolder= fso.GetFolder(MyFolder)  
        GetSize = FormatSize(objFolder.Size)
    End Function
    '*******************************************************************
    'Function to format a number into typical size scales
    Function FormatSize(iSize)
       aLabel = Array("bytes", "KB", "MB", "GB", "TB")
       For i = 0 to 4
            If iSize > 1024 Then
                iSize = iSize / 1024
            Else
                Exit For
            End If
       Next
       FormatSize = Round(iSize,2) & " " & aLabel(i)
    End Function
    '*******************************************************************
    </script>
    </job>
    
    0 讨论(0)
提交回复
热议问题