Copyright © 2003-2010 by Prof. Timo Salmi  
Last modified Fri 16-Jul-2010 08:06:01

Assorted NT/2000/XP/.. CMD.EXE Script Tricks
From the html version of the tscmd.zip 1cmdfaq.txt file
To the Description and the Index

This page is edited from the 1cmdfaq.txt faq-file contained in my tscmd.zip command line interface (CLI) collection. That zipped file has much additional material, including a number of detached .cmd script files. It is recommended that you also get the zipped version as a companion.

Please see "The Description and the Index page" for the conditions of usage and other such information.

43} Is there a way of counting the number of files in a folder / subfolders?

First off, let's exclude the files in the subfolders from the consideration and take the information directly from the folder listing
  @echo off & setlocal enableextensions
  set folder_=C:\_D\TEST
  for /f "tokens=1" %%f in ('
    dir "%folder_%\*.*"^|findstr /c:" File(s)"') do (
      set countf_=%%f)
  for /f "tokens=1" %%d in ('
    dir "%folder_%\*.*"^|findstr /c:" Dir(s)"') do (
      set countd_=%%d)
  echo %folder_%
  echo Found %countf_% files, %countd_% folders
  endlocal & goto :EOF

The output might be something like
  Found 20 files, 2 folders
Note that the above includes the . and .. inherent in every folder.

Next let's include the subfolders and actually count the number of files and subfolders instead of extracting the information from the folder summary. (The . and .. are excluded.)
  @echo off & setlocal enableextensions
  set startFolder=C:\_D
  set /a countd_=0
  set /a countf_=0
  for /f %%f in ('dir /s /b /a:d "%startFolder%\*.*"') do set /a countd_+=1
  for /f %%f in ('dir /s /b /a:-d "%startFolder%\*.*"') do set /a countf_+=1
  echo Found %countf_% files, %countd_% subfolders
  echo in and below "%startFolder%"
  endlocal & goto :EOF

The output might be e.g.
  Found 2801 files, 146 subfolders
  in and below "C:\_D"
If you wish to count what is on C: substitute in the above (without a backslash)
  set startFolder=C:
A word of caution. This one may take quite a long while to process.

Let's not stop there, but list the files together with an ordinal number.
  @echo off & setlocal enableextensions
  set startFolder=C:\_D
  set /a FileCount_=0
  for /f "delims=" %%f in ('
    dir /s /b /a:-d /o:e "%startFolder%\*.*"') do (
      call :ListOneFile "%%f")
  endlocal & goto :EOF
  :: ===========================================

  set /a FileCount_+=1
  call :FuncRightJustify5 %FileCount_% FileCount_
  echo %FileCount_: =0% %*
  goto :EOF
  :: ===========================================

  :FuncRightJustify5 arg1 arg2
  setlocal enableextensions
  set number_= %1
  set number_=%number_:~-5%
  endlocal & set "%2=%number_%" & Goto :EOF

The output might be something like
  00001 "C:\_D\HAE.BAT"
  00017 "C:\_D\BAS\CMDFAQ2.CMD"
  00018 "C:\_D\BAS\FAQPAS.PAS"
  00019 "C:\_D\BAS\test & 3.txt"
  00020 "C:\_D\BAS\test (4!).txt"
  00021 "C:\_D\BAS\VBSFAQ.VBS"
  02800 "C:\_D\WORD\WORDVB.TXT"
  02801 "C:\_D\WORD\wordxml.xml"

The problem can also be solved with a VBS-aided script (giving the same output as in the above)
  @echo off & setlocal enableextensions
  set topfolder_=C:\_D
  :: Build a Visual Basic Script

  set skip=
  set vbs_=%temp%\tmp$$$.vbs
  findstr "'%skip%VBS" "%~f0" > "%vbs_%"
  :: Run it with Microsoft Windows Script Host Version 5.6

  cscript //nologo "%vbs_%" "%topfolder_%"
  :: Clean up

  for %%f in ("%vbs_%") do if exist %%f del %%f
  endlocal & goto :EOF
  ' The Visual Basic Script

  Sub TraverseOneFolder(foldername) 'VBS
    Dim fso, f, f1, fc 'VBS
    Set fso = CreateObject("Scripting.FileSystemObject") 'VBS
    Set f = fso.GetFolder(foldername) 'VBS
    Set fc = f.Files 'VBS
    For Each f1 in fc 'VBS
      i = i + 1 'VBS
      Wscript.Echo PadFn(CStr(i),5), f1 'VBS
    Next 'VBS
  End Sub 'VBS
  Sub TraverseManyFolders(startfoldername) 'VBS
    Dim fso, f, f1, sf 'VBS
    Set fso = CreateObject("Scripting.FileSystemObject") 'VBS
    Set f = fso.GetFolder(startfoldername) 'VBS
    If Instr (1, Ucase(f), "RECYCLER") = 0 Then 'VBS
      TraverseOneFolder(f) 'VBS
    End If 'VBS
    Set sf = f.SubFolders 'VBS
    For Each f1 in sf 'VBS
      If Instr (1, Ucase(f1), "RECYCLER") = 0 Then 'VBS
        TraverseManyFolders(f1) 'VBS
      End If 'VBS
    Next 'VBS
  End Sub 'VBS
  Function PadFn (str, n) 'VBS
    If Len(str) > n Then 'VBS
      PadFn = str 'VBS
    Else 'VBS
      PadFn = Right(String(n-1,"0")&str,n) 'VBS
    End If 'VBS
  End Function 'VBS
  ' The main script

  i = 0 'VBS
  TraverseManyFolders(WScript.Arguments.Unnamed(0)) 'VBS
If you just wish to count the top folder change TraverseManyFolders to TraverseOneFolder on the last line.