Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- @echo off
- echo/
- echo dirsize v1.0.12
- echo (c) 2017 GCRaistlin. Licensed under GNU GPL v3.
- echo/
- setlocal disabledelayedexpansion
- if defined IgnoreError set IgnoreError=
- rem Если флаг установлен, скрипт игнорирует ошибки обработки каталогов
- rem set IgnoreError=1
- rem Разделитель имени каталога и размера в выводе. Если результат
- rem предполагается парсить, то рекомендуется использовать один из символов:
- rem "<|>". По умолчанию - пробел.
- rem set "Separator=|"
- set Root=%1
- rem Don't delete 2 empty lines above, or else the script will fail if
- rem the argument is ended with "^".
- 2>nul (for /f "tokens=1 delims==" %%A in ('set Error') do set "%%A=")
- set Error2=Invalid root directory
- set Error4=Size too big
- if not defined Root goto _Help
- call :_IsDir %Root%
- if errorlevel 1 (set errorlevel=2& goto _Exit)
- rem Уровни текущего (обрабатываемого) и предыдущего (обработанного) каталога
- rem (количество "\" в полном имени каталога)
- if defined Lvl set Lvl=
- rem PrevLvl устанавливаем в невозможное значение, т. к. пустое не годится -
- rem см. (*)
- set PrevLvl=0
- rem Уровень %Root%
- if defined Lvl0 set Lvl0=
- rem См. ниже
- 2>nul (for /f "tokens=1 delims==" %%A in ('set Name') do set "%%A=")
- 2>nul (for /f "tokens=1 delims==" %%A in ('set SizeB') do set "%%A=")
- 2>nul (for /f "tokens=1 delims==" %%A in ('set SizeGB') do set "%%A=")
- rem Флаг обнаружения ошибки в файловой структуре
- if defined Dirty set Dirty=
- :TmpFile
- set "TmpFile=%Temp%\%~n0_%random%.txt"
- if exist "%TmpFile%" goto TmpFile
- >nul copy nul "%TmpFile%" || (set errorlevel=3& goto _Exit)
- if defined IgnoreError (
- echo WARNING: IgnoreError flag is set. Directory sizes may be not reliable.
- echo/
- )
- if not defined Separator set "Separator= "
- >nul chcp 65001
- for /f "delims=" %%A in ('^(for /r %Root% %%Z in ^(.^) do @echo "%%Z"^) ^& echo :::') do (
- if errorlevel 1 goto _Exit
- set CurDir=%%~A
- setlocal enabledelayedexpansion
- if defined Lvl set PrevLvl=!Lvl!
- rem Определяем уровень %CurDir%
- if "%%~A" == ":::" (
- set Lvl=0
- ) else (
- >"!TmpFile!" echo !CurDir!||(set errorlevel=3& goto _Exit)
- for %%A in ("!TmpFile!") do set /a Lvl=%%~zA
- >"!TmpFile!" echo !CurDir:\=!||(set errorlevel=3& goto _Exit)
- for %%A in ("!TmpFile!") do set /a Lvl-=%%~zA
- if not defined Lvl0 set Lvl0=!Lvl!
- )
- for /f "delims=| tokens=1-4" %%B in ("!Lvl!|!Lvl0!|!CurDir:~,-2!|!PrevLvl!") do (
- endlocal
- set Lvl=%%B
- set Lvl0=%%C
- if not _0 == _%%E (
- set PrevLvl=%%E
- rem (*) Тут можно использовать только численное сравнение, иначе ошибка
- rem при работе с уровнями >9
- if %%B gtr %%E (for /f %%z in ("") do cd) || rem
- if not errorlevel 1 (
- rem Текущий каталог не является подкаталогом предыдущего каталога, либо
- rem предыдущий каталог был последним.
- for /l %%F in (%%E,-1,%%B) do (
- rem Чтобы не уйти выше корня при обработке ":"
- if %%F geq %%C (
- rem Выводим информацию о предыдущем каталоге и всех его предках до
- rem уровня текущего включительно
- setlocal enabledelayedexpansion
- if !SizeGB%%F! gtr 0 (
- rem Если размер более 1 GB, значение SizeB нужно дополнить слева
- rem нулями.
- set SizeB%%F=00000000!SizeB%%F!
- echo !Name%%F!!Separator!!SizeGB%%F!!SizeB%%F:~-9!
- ) else (
- echo !Name%%F!!Separator!!SizeB%%F!
- )
- endlocal
- rem Стираем переменные
- set SizeB%%F=
- set SizeGB%%F=
- )
- )
- )
- )
- if not _%%B == _0 (
- if defined IgnoreError (
- set /a 0
- ) else (
- rem Пытаемся прочесть содержимое текущего каталога
- >nul 2>&1 (dir /b "%%D\?" || dir /b /ah "%%D\?" || dir /b /as "%%D\?")
- )
- if errorlevel 1 (
- echo/
- echo Error processing directory %%D.
- goto _Exit
- ) else (
- (for /f "eol= delims=" %%F in ('2^>nul dir /b /a-d "%%D\*"') do (
- for %%G in ("%%D\%%F") do (
- set Size=%%~zG
- if not defined Size (
- rem Повреждение файловой структуры
- if not defined Dirty set Dirty=1
- rem Получаем размер через dir
- (for /f %%z in ("") do cd) || rem
- for /f "skip=5 tokens=3" %%H in ('dir /-c "%%D\%%F"') do (
- if errorlevel 1 set Size=%%H
- )
- (for /f %%z in ("") do cd) || rem
- )
- setlocal enabledelayedexpansion
- if not "" == "!Size:~,-9!" (
- rem Размер текущего файла > 1 GB
- set /a SizeGB%%B+=!Size:~,-9!
- if !SizeGB%%B! lss 0 (set errorlevel=4& goto _Exit)
- set Size=!Size:~-9!
- rem Убираем ведущие нули у Size
- for /l %%H in (0,1,7) do (
- if not errorlevel 1 if not "!Size:~%%H,1!" == "0" (
- set Size=!Size:~%%H!
- (for /f %%z in ("") do cd) || rem
- )
- )
- )
- set Size=!Size:~-9!
- set /a SizeB%%B+=!Size!
- set /a SizeGB%%B+=SizeB%%B/1000000000,SizeB%%B%%=1000000000
- if !SizeGB%%B! lss 0 (set errorlevel=4& goto _Exit)
- for /f "tokens=1,2" %%H in ("!SizeB%%B! !SizeGB%%B!") do (
- endlocal
- set SizeB%%B=%%H
- set SizeGB%%B=%%I
- )
- )
- )) || (
- rem В текущем каталоге нет файлов
- set SizeB%%B=0
- set SizeB%%GB=0
- )
- )
- )
- for /l %%F in (%%B,-1,%%C) do (
- if not %%F == %%B (
- rem Увеличиваем значения size-переменных для всех предков текущего
- rem каталога на его размер
- set /a SizeB%%F+=SizeB%%B
- set /a SizeGB%%F+=SizeB%%F/1000000000,SizeB%%F%%=1000000000
- set /a SizeGB%%F+=SizeGB%%B
- )
- )
- set Name%%B=%%D
- )
- )
- if defined Dirty (
- echo/
- echo WARNING: errors in the file system were detected.
- )
- goto _Exit
- :_IsFile <obj>
- rem Exit codes:
- rem 2: <obj> does not exist
- rem 1: <obj> is a directory
- rem 0: <obj> is a file
- rem -1: Invalid syntax
- :_IsDir <obj>
- rem Exit codes:
- rem 2: <obj> does not exist
- rem 1: <obj> is a file
- rem 0: <obj> is a directory
- rem -1: Invalid syntax
- setlocal disabledelayedexpansion
- if /i "%0" == ":_IsFile" (
- set not=not
- ) else (
- if defined not set not=
- )
- set Obj=%1
- if defined Obj if not "" == "%Obj:"=%" goto $endif
- echo/
- echo Usage:
- echo call %0 ^<obj^>
- exit /b -1
- :$endif
- if not "%Obj:"=%" == "%Obj:"=@%" set "Obj=%Obj:"=%"
- if not "%Obj:?=%" == "%Obj%" exit /b 2
- if not exist "%Obj%" exit /b 2
- for %%A in ("%Obj%") do set Attr=%%~aA
- if /i %not% "-" == "%Attr:~,1%" exit /b 1
- exit /b
- :_Help
- echo Calculates sizes of each directory in the directory tree.
- echo/
- echo Usage:
- echo %~nx0 ^<root^>
- echo/
- echo Exit codes: 0 OK
- echo 1 Error processing directory
- echo 2 %Error2%
- echo 3 General error
- echo 4 %Error4%
- echo -1 Invalid syntax
- set errorlevel=-1
- :_Exit
- if defined Error%errorlevel% (
- set errorlevel=%errorlevel%
- if not "!!" == "" setlocal enabledelayedexpansion
- echo !Error%errorlevel%!.
- )
- if "!!" == "" endlocal
- (
- for %%A in ("%TmpFile%" "%TmpFile2%" "%TmpFile3%") do if exist %%A del %%A
- echo/
- echo Exit code: %errorlevel%
- rem if %errorlevel% gtr 0 pause
- exit /b %errorlevel%
- )
- Переменные с <lvl> в имени всегда содержат информацию по ветви текущего
- обрабатываемого каталога.
- Переменная вида Name<lvl> содержит имя каталога уровня <lvl>.
- Переменные вида SizeB<lvl> и SizeGB<lvl> содержат текущий подсчитанный размер
- каталога уровня <lvl> - часть меньше GB и целые GB соответственно.
- Напр., если %Root% = C:\foo, то после обработки C:\foo\bar\data имеем:
- Lvl = 2 (относительный уровень)
- Name2= C:\foo\bar\data
- SizeB2 = <суммарный размер файлов в C:\foo\bar\data за вычетом целых GB>
- SizeGB2 = <суммарный размер файлов в C:\foo\bar\data в целых GB>
- Name1= C:\foo\bar
- SizeB1 = <суммарный размер файлов в C:\foo\bar и уже обработанных его
- подкаталогов за вычетом целых GB + SizeB2>
- SizeGB1 = <суммарный размер файлов C:\foo\bar и уже обработанных его
- подкаталогов в целых GB + SizeGB2>
- Name0 = C:\foo
- SizeB0 = <суммарный размер файлов в C:\foo и уже обработанных его подкаталогов
- за вычетом целых GB + SizeB2>
- SizeGB0 = <суммарный размер файлов C:\foo и уже обработанных его подкаталогов в
- целых GB + SizeGB2>
- Под "уже обработанными" подразумеваются каталоги, пройденные по всей глубине
- уровней.
- При обработке следующего каталога - C:\foo\bar2 - на экран будут выведены
- данные по каталогам:
- C:\foo\bar\data
- C:\foo\bar
- Затем будут уничтожены <lvl>-переменные с <lvl> = 1 и 2. И наконец:
- Lvl = 1
- заново определены Name1, SizeB1 и SizeGB1, пересчитаны SizeB0 и SizeGB0.
- Changelog
- v1.0.12
- [+] Поддержка юникодных имен.
- [+] Сообщаем об обнаружении ошибок в файловой структуре.
- [*] Улучшена обработка ошибок.
- v1.0.10
- [+] Настраиваемый разделитель имени и размера. Устанавливается переменной внутри скрипта.
- v1.0.9
- [+] Поддержка флага IgnoreError - если установлен, то ошибки при чтении содержимого каталогов (из-за юникодных символов в имени или недостаточных прав доступа) игнорируются. Устанавливается переменной внутри скрипта.
- [-] Неправильно обрабатывались каталоги уровнем 10 и глубже.
- [-] Пропускались каталоги с атрибутами Hidden и/или System.
- [+] Показываются сведения о скрипте в начале работы и код ошибки в конце.
- [+] Краткое описание алгоритма в конце скрипта.
- v1.0.3
- [*] Initial public release.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement