Пакетный файл для отображения размера каталога

Я хочу изменить этот скрипт. Я не могу заставить его принимать символы подстановки:

@echo off
setLocal EnableDelayedExpansion
set /a value=0
set /a sum=0
FOR /R %1 %%I IN (*) DO (
set /a value=%%~zI/1024
set /a sum=!sum!+!value!
)
@echo Size is: !sum! k

Он находится в пакетном файле с именем dirsize и вызывается так:

dirsize c:\folder

Я хочу, чтобы он проверял размеры папок для меня. Вот пример, кеш в firefox:

dirsize C:\users\%username%\AppData\Local\Mozilla\Firefox\*.default\Cache

Он возвращает значение 0.

Но если я пойду

dirsize C:\users\%username%\AppData\Local\Mozilla\Firefox\sr1znnb4.default\Cache

Это работает, и я получаю значение 55322.


person Community    schedule 17.04.2009    source источник
comment
Попробуйте сделать первую строку: @IF NOT DEFINED _ECHO ECHO OFF, тогда вы можете установить _ECHO при отладке.   -  person Jay Bazuzi    schedule 17.08.2009


Ответы (6)


PowerShell, конечно, делает это легко:

    (gci . -Recurse | Measure-Object -Property Length -Sum).Sum

И PowerShell уже установлен в Windows 7. Присоединяйтесь! :-)

Кроме того, C:\users\%USERNAME%\AppData\ не является надежным способом поиска AppData. Попробуйте %APPDATA% (или $env:APPDATA в PowerShell).

person Jay Bazuzi    schedule 17.08.2009

Хорошо, для начала допустим, что подстановочные знаки плохо поддерживаются во всех пакетных файлах, особенно в циклах for.
Вот что я придумал:

DirSize.cmd "допустимый путь"

@echo off
rem Args[1]= "Path" or "valid path with wildcard"
set _size=0
set dRaw=%~1
echo %~1|findstr "*"&& set dSource=%~dp1|| (
    set dSource=%~1\
    if not "%dRaw:~-1%"=="\" set dRaw=%dRaw%\
)
for /f "delims=" %%D in ('dir /ad /b %dRaw%') do call :DirSize "%dSource%%%~D"
set /a size=_size/1024
echo size=%size% k (%_size% bytes)
exit /b 0

:DirSize
    call :FileSize "%~1"
    for /f "delims=" %%d in ('dir /ad /b "%~1"2^>nul') do call :DirSize "%~1\%%~d"
    exit /b 0

:FileSize
    for /f "delims=" %%f in ('dir /a-d /b "%~1\"2^>nul') do for %%F in (%1\%%f) do set /a _size+=%%~zF
    exit /b 0

___Usage___
Аргумент: Должен быть путь (не файл), содержащий подстановочные знаки или без них. Путь должен быть допустимым при вводе dir path

___Примечания___
Этот сценарий проверяет все файлы и подкаталоги, даже скрытые/системные. измените аргумент dir /a и добавьте -h-s (например, /ad-h-s), чтобы устранить это поведение.

Теперь я пересмотрел проверку аргументов по своему вкусу, поэтому я думаю, что ее можно использовать.

Надеюсь, это поможет.

person Jay    schedule 24.08.2009
comment
Это отлично работает для меня! Я добавил вверху...; if [%1]==[] goto :Usage&exit /b 0 if [%1]==[/?] goto :Usage&exit /b 0 ... а затем внизу сделал использование и примечания в функции использования несколько повторов, заканчивающихся на /b 0. Большое спасибо! - person AnneTheAgile; 05.09.2012
comment
Я рад, что это может помочь снова. Повторное использование кода, тем лучше :) - person Jay; 21.11.2012

Вам нужно будет обернуть то, что у вас есть в настоящее время, в другой цикл for, который расширяет * в серию каталогов.

So

@echo off
setLocal EnableDelayedExpansion
set /a sum=0
for /d %%D in (%1) do (
  FOR /R %%D %%I IN (*) DO (
    set /a value=%%~zI/1024
    set /a sum=!sum!+!value!
  )
)
echo Size is: !sum! k

может работать (хотя и не проверено, но должно дать вам общее представление)

person Joey    schedule 17.04.2009

Если у вас есть версия grep для Windows (ее можно найти на странице утилиты GNU для Win32), вы можете что-то сделать как это:

dir /s %1 | grep --after-context=1 "Total Files Listed:"
person Patrick Cuff    schedule 17.04.2009

Этот код увеличит лимит размера каталога до 2 000 000 ТБ и будет отображать более реальный размер, что будет полезно, если папка содержит слишком много файлов.

rem SET DIR=%1
SET DIR=C:\DIR1\

IF NOT EXIST "%DIR%" (
ECHO Directory "%DIR%" does not exist.
goto END
)

setlocal EnableDelayedExpansion

set GB=
set SIZE=

set exp=000000000

FOR /R "%DIR%" %%F IN (*) DO (
set /a SIZE=!SIZE!+%%~zF
if !SIZE! geq 1!exp! (
set /a GB=!GB!+!SIZE:~0,-9!
for /f "tokens=* delims=0" %%a in ("!SIZE:~-9!") do set SIZE=%%a
)
)
if not defined SIZE set SIZE=0
if not defined GB goto EOS

FOR /L %%N IN (1,1,9) DO (
if "!SIZE:~%%N!" == "" (
set SIZE=!GB!!exp:~%%N!!SIZE!
goto EOS
)
)
:EOS

call :Divide !SIZE! 1024 SIZEKB

echo Size is: !SIZE!B (!SIZEKB!kB)

endlocal

:END
pause
exit

:Divide
set Num1=%~1
set Num2=%~2
set %3=
set Num=
set Number=
IF !Num2! EQU 0 goto :EOF
FOR /L %%N IN (0,1,18) DO (
if "!Num1:~%%N!" == "" goto :EOD
set Number=!Number!!Num1:~%%N,1!
if !Number! geq !Num2! (
  set /a quotient=!Number!/!Num2!
  set /a Number=!Number!-!quotient!*!Num2!
  if !Number! equ 0 set Number=
  set Num=!Num!!quotient!
) else (
  if defined Num set Num=!Num!0
)
)
:EOD
if not defined Num set Num=0
set %3=%Num%
goto :EOF
person Олександр Іванків    schedule 16.08.2014
comment
Кажется, это правильно вычисляет сумму размера файла, но в моей системе (Win10) я попробовал этот скрипт и получил следующий результат: Size of "C:\Program Files": 14506 bytes 2 Kb 0 Mb 0 Gb Это явно неправильно, но когда я просматриваю свойства этой папки, File Explorer дает мне 145,063,491 bytes который Я заметил, что первые 5 цифр совпадают с числом, отображаемым вашим скриптом. Очевидно, что что-то не так с математикой в ​​Windows 10, и это число представляет собой единицу в 10 000 раз больше, чем байт. - person VictorB; 24.06.2020

В 10 раз быстрее, чем через FOR. С преимуществом возможности использовать любой из разрешенных параметров команды DIR (в данном случае /S)

@ECHO OFF

SET folder="C:\WINDOWS"

call:timer

ECHO Processing, please wait...

CALL :folderSize size %folder% "/S"


CALL :strNumDivide sizeKb %size% 1024
CALL :strNumDivide sizeMb %sizeKb% 1024
CALL :strNumDivide sizeGb %sizeMb% 1024

CALL :formatNumber size %size%
CALL :formatNumber sizeKb %sizeKb%
CALL :formatNumber sizeMb %sizeMb%
CALL :formatNumber sizeGb %sizeGb%

ECHO.
ECHO Size of %folder%: 
ECHO.

ECHO %size% bytes
ECHO %sizeKb% Kb
ECHO %sizeMb% Mb
ECHO %sizeGb% Gb
ECHO.

pause
exit /b

:: Function to calculate the size of a directory and its subdirectories
::----------------------------------------------------------------------
:folderSize <returnVariableName> <folder> [DIR parameters]
    SetLocal EnableExtensions EnableDelayedExpansion

    SET folder=%2
    SET params=%~3

    IF NOT DEFINED folder SET folder="%CD%"

    DIR %params% /W "%folder:"=%" > %TEMP%\folderSize.tmp

    FOR /F "tokens=1 delims=:" %%x IN ('findstr /n /e ":" %TEMP%\folderSize.tmp') DO (SET line=%%x)

    IF DEFINED line (

        SET /A line = !line! + 1

        FOR /F "tokens=4 delims= " %%i IN ('findstr /n "bytes" %TEMP%\folderSize.tmp^|findstr "!line!:"') DO (SET size=%%i)
        SET size=!size:.=!

    ) ELSE (

        FOR /F "tokens=3 delims= " %%i IN ('findstr /e "bytes" %TEMP%\folderSize.tmp') DO (SET size=%%i)
        SET size=!size:.=!

    )

    DEL %TEMP%\folderSize.tmp > nul

    EndLocal & SET "%~1=%size%"

GOTO:EOF



:: Extras functions to convert between different units and to give numerical format
:: --------------------------------------------------------------------------------
:strNumDivide <returnVariableName> <stringNum> <divisor>
    SetLocal EnableExtensions EnableDelayedExpansion 

    SET strNum=%~2
    SET divisor=%~3

    SET result=
    SET number=

    IF !divisor! EQU 0 GOTO:EOF

    FOR /L %%n IN (0,1,18) DO (
        IF NOT "!strNum:~%%n!" == "" (
            SET number=!number!!strNum:~%%n,1!

            IF !number! GEQ !divisor! (
                SET /A quotient=!number! / !divisor!
                SET /A number=!number! - !quotient! * !divisor!
                IF !number! EQU 0 SET number=
                SET result=!result!!quotient!
            ) ELSE (
                IF DEFINED result SET result=!result!0
            )
        )
    )

    IF NOT DEFINED result SET "result=0"
    EndLocal & SET "%~1=%result%"

GOTO:EOF


:formatNumber <returnVariableName> <number> [separator [group size]] 
    SetLocal EnableExtensions EnableDelayedExpansion 
    SET "raw=%~2"
    SET "separator=%~3" 
    SET "group=%~4" 
    SET "answer=" 
    IF NOT DEFINED raw GOTO :EOF
    IF NOT DEFINED separator SET "separator=."
    IF NOT DEFINED group SET "group=3"

    FOR %%g IN (-%group%) DO (
        FOR /F "tokens=1,2 delims=,." %%a IN ("%raw%") DO ( 
            SET int=%%a
            SET frac=%%b

            FOR /F "delims=:" %%c IN ('^(ECHO;!int!^& Echo.NEXT LINE^)^|FindStr /O "NEXT LINE"') DO (
                SET /A length=%%c-3
            ) 

            FOR %%c IN (!length!) DO ( 
                SET radix=!raw:~%%c,1!
            )

            FOR /L %%i IN (!length!, %%g, 1) DO ( 
                SET answer=!int:~%%g!!separator!!answer! 
                SET int=!int:~0,%%g!
            ) 
        ) 
    )
    SET answer=%answer: =%
    SET answer=%answer:~0,-1%

    EndLocal & SET "%~1=%answer%%radix%%frac%" 
Goto :EOF 

Пример вывода результата: (в примере подпрограмме потребовалось 3 секунды, чтобы вычислить размер C:\WINDOWS размером 28GB)

Processing, please wait...

Size of "C:\WINDOWS":

30.936.389.769 bytes
30.211.318 Kb
29.503 Mb
28 Gb


Elapsed Time: 3 secs
person PHC    schedule 19.05.2015