List each subdirectory and the number of files within it using cmd.exe

I have several subdirectories that contain files, and I want to list each subdirectory and beside it the number of files (*.html specifically) within that subdirectory. For example, I am in "C:\Users\user1\Desktop\temp" and I want the following listing:

"C:\Users\user1\Desktop\temp\subdir1"  5 files
"C:\Users\user1\Desktop\temp\subdir2"  4 files
"C:\Users\user1\Desktop\temp\subdir2\subdir1"  7 files

I tried using this code, but it only lists the number of files in the current directory:

dir /b *.html /s 2> nul | find "" /v /c > tmp && set /p count=<tmp && del tmp && echo %count%

Solution 1:

I highly encourage you to learn PowerShell - it so much more complete and consistent as a language than batch. So here's the solution in PowerShell

Get-ChildItem -recurse -directory | foreach {$c = ((Get-ChildItem $_ -File *.html| Measure-Object).Count); write-host $_ $c}

or the shorter version

gci -recurse -directory | foreach {$c = ((gci $_ -File *.html| Measure).Count); write-host $_ $c}

This command gets the list of directories, pipes them to foreach which iterates through them one at a time putting the name in the $_ variable. Then we list the files that match the pattern in each directory, count the result and save the count in $c variable. Finally we write the path (still in $_) and the count from $c

Solution 2:

This works for me (I just wrote it). I have combined two methods of isolating calls. You will note that I have broken apart searching the directories from the actual counting of files.

The first block uses for /R and the call :label functionality to search the directory structure and pass the directories found to a function called :CountFilesInDir. The CountFilesInDir function uses another method to allow working with a variable while in a loop with the EnableDelayedExpansion option.

I do this for two reasons. One, I like to break my code into functions. :) .. two, I am showing you both methods of getting a variable set while in a loop.

Last, you will note a variable before the first loop to decide what type of files you are trying to count called TypeToCount.

    @echo off

    SetLocal EnableDelayedExpansion
    Set TypeToCount=*.html
    for /R %%d in (.) do call :CountFilesInDir "%%d" "%TypeToCount%"
    EndLocal
    goto :EOF

    ::::::::::::::::::::::::::::::::::::::::::::::::::
    :CountFilesInDir
    ::::::::::::::::::::::::::::::::::::::::::::::::::
    SetLocal
    Set InputPath=%~1
    Set TypeToCount=%~2
    pushd %InputPath%

    Set FileCount=0
    for /F "delims=" %%f in ('dir /a-d /b %TypeToCount% 2^>nul') do (
      Set /a FileCount = !FileCount! + 1
    ) 

    echo "%InputPath:~0,-2%" %FileCount% files
    popd
    EndLocal
    goto :EOF