160} How do I get a list of all my folders with and sorted by size?
@echo off & setlocal enableextensions
enabledelayedexpansion
::
:: Set the auxiliary file names
set temp_=%temp%
if defined mytemp set temp_=%mytemp%
set FolderContent=%temp_%\FullContent.dir
set SizeAndFolder=%temp_%\SizeAndFolder.dir
set FolderList=%temp_%\FolderList.dir
::
:: Make the folder list
dir /s /-c "C:\" > "%FolderContent%"
:: Traverse it
findstr ".Directory.of. .File(s)." "%FolderContent%">"%SizeAndFolder%"
set Flag=
for /f "tokens=* delims= " %%a in (
'type "%SizeAndFolder%"') do (
if not defined Flag (
set Folder=%%a
set Flag=true
) else (
set Size= %%a
set Flag=
echo !Size:~-20! !Folder!>>"%FolderList%"
)
)
::
:: Show the result
sort "%FolderList%"
call :WarnIfExlamations
::
:: Clean up
for %%f in ("%FolderContent%" "%SizeAndFolder%" "%FolderList%") do (
if exist %%f del %%f)
endlocal & goto :EOF
::
:: ======================================================
:WarnIfExlamations
setlocal enableextensions
disabledelayedexpansion
findstr "!" "%SizeAndFolder%">nul
if %errorlevel% GTR 0 goto :EOF
echo.
echo Warning: Folder names with exclamation marks ^(!^) encountered
endlocal & goto :EOF
The output might end with something like
242904830 bytes Directory of C:\WINDOWS\system32\dllcache
359978283 bytes Directory of C:\WINDOWS\$NtServicePackUninstall$
429340336 bytes Directory of C:\WINDOWS\system32
497131051 bytes Directory of C:\WINDOWS\ServicePackFiles\i386
Unfortunately, there is the familiar catch. Because of the enabled
delayedexpansion any exlamation marks (!) in the names will be
dropped.
Note that the solution above gives the size of the immediate folder.
That is, the material in the subfolders does not accumulate in the
size of a folder. A different answer is gotten with a VBScript-aided
solution. If there are any subfolders in a folder, the material in
the subfolders is fully included in the upper-level folder's size
information. Furthermore, the VBS solution is not affected potential
exclamation marks in the folder names.
@echo off & setlocal enableextensions
::
if "%~1"=="" (echo Usage: %~f0 "[FolderName]"&goto :EOF)
set debug_=true
set debug_=
::
:: Build a Visual Basic Script
set skip=
set temp_=%temp%
if defined mytemp if exist "%mytemp%\" set temp_=%mytemp%
set vbs_=%temp_%\tmp$$$.vbs
>"%vbs_%" findstr "'%skip%VBS" "%~f0"
::
:: Run the script with Microsoft Windows Script Host Version 5.6
if defined debug_ (
type "%vbs_%"
goto _cleanup)
cscript //nologo "%vbs_%" "%~1"
::
:_cleanup
for %%f in ("%vbs_%") do if exist %%f del %%f
endlocal & goto :EOF
'
'The Visual Basic Script
'
Function FolderSizeFn(folderspec) 'VBS
Dim fso, f 'VBS
Set fso = CreateObject("Scripting.FileSystemObject") 'VBS
Set f = fso.GetFolder(folderspec) 'VBS
FolderSizeFn = f.size 'VBS
End Function 'VBS
'
Function TraverseSubFolders(StartFolderName) 'VBS
Dim fso, f, f1, sf 'VBS
Set fso = CreateObject("Scripting.FileSystemObject") 'VBS
Set f = fso.GetFolder(StartFolderName) 'VBS
Set sf = f.SubFolders 'VBS
For Each f1 in sf 'VBS
Wscript.Echo PadSpFn(FolderSizeFn(f1),15) & " " & f1 'VBS
TraverseSubFolders(f1) 'VBS
Next 'VBS
End Function 'VBS
'
Function TraverseStartFolder(StartFolderName) 'VBS
Dim fso, f 'VBS
Set fso = CreateObject("Scripting.FileSystemObject") 'VBS
Set f = fso.GetFolder(StartFolderName) 'VBS
Wscript.Echo PadSpFN(FolderSizeFn(f),15) & " " & f 'VBS
End Function 'VBS
'
Function PadSpFn (str, n) 'VBS
PadSpFn = Right(String(n-1," ")&str,n) 'VBS
End Function 'VBS ,
'
Set arg = WScript.Arguments 'VBS
TraverseStartFolder(arg(0)) 'VBS
TraverseSubFolders(arg(0)) 'VBS
An edited example of the output
C:\_D\TEST>cmdfaq C:\_F\TEXT\ | sort
0 C:\_F\TEXT\PROFOS
9770 C:\_F\TEXT\EMAIL
11264 C:\_F\TEXT\INFO
339548 C:\_F\TEXT\LIST
486585 C:\_F\TEXT\PROFLT
573877 C:\_F\TEXT\OTHERS\PUBLICAT
2311953 C:\_F\TEXT\BYROK
12779759 C:\_F\TEXT\OTHERS
19349999 C:\_F\TEXT
Let's return to the original task of getting with pure script the size
of each folder counting only the size of files in it but not below the
folder. At the same time avoid the poison character problem. The
solution below does these, but it is very slow even on a fast
computer.
@echo off & setlocal enableextensions
::
if "%~1"=="" (echo Usage: %~f0 "[FirstFolderName]"&goto :EOF)
::
set tempdir_=%temp%\temp$$$.dir
for %%f in ("%tempdir_%") do if exist %%f del %%f
::
call :GetFolderSize "%~1">"%tempdir_%"
for /f "tokens=*" %%a in ('dir /s /b /a:d "%~1"') do (
call :GetFolderSize "%%a")>>"%tempdir_%"
sort "%tempdir_%"
::
for %%f in ("%tempdir_%") do if exist %%f del %%f
endlocal & goto :EOF
::
:: ====================================================
:GetFolderSize
setlocal enableextensions
for /f "tokens=3" %%a in ('
dir /-c "%~1"^|find " File(s) "') do (
call :DisplayFolderInfo "%%a" "%~1")
endlocal & goto :EOF
::
:: ====================================================
:DisplayFolderInfo
setlocal enableextensions
set var_= %~1
set var_=%var_:~-15%
echo %var_% "%~2"
endlocal & goto :EOF
The output could be e.g.
C:\_D\TEST>cmdfaq "C:\_K"
0 "C:\_K"
0 "C:\_K\test & dir!"
370725 "C:\_K\CATEYE"
1091783 "C:\_K\SCANOHJE"
2578410 "C:\_K\TOPFIELD\NotOk"
4228788 "C:\_K\PMAX"
4875161 "C:\_K\TPLINK"
10934167 "C:\_K\TOPFIELD"
Not that it makes any difference, but in the above
::
call :GetFolderSize "%~1">"%tempdir_%"
for /f "tokens=*" %%a in ('dir /s /b /a:d "%~1"') do (
call :GetFolderSize "%%a")>>"%tempdir_%"
sort "%tempdir_%"
::
could as well be written as
::
call :GetFolderSize "%~1">"%tempdir_%"
for /r "%~1" %%a in (.) do (
call :GetFolderSize "%%a")>>"%tempdir_%"
sort "%tempdir_%"
::