<http://www.netikka.net/tsneti/info/tscmd057.htm>
Copyright © 2003-2010 by Prof. Timo Salmi  
Last modified Mon 19-Apr-2010 17:00:25

 
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.



57} How do I get a list of all my empty folders on c:\ ?

Empty folders, i.e. no files or subfolders. (But first an important WARNING! Do not go and indiscriminately delete empty folders, since the system or the programs on your computer may need them.) Here is one solution option. I first attempted this with a "pure" CMD script, but because of the possibility of hidden files and hidden subfolders the results were too unstable.

Note that on a shared or system-managed computer you might get access denied errors. If so, do not start high up the root of C:\

  @echo off & setlocal enableextensions
  :: Build a Visual Basic Script
  set skip=
  findstr "'%skip%VBS" "%~f0" > "%temp%\tmp$$$.vbs"
  :: Start from Folder (Customize, if need be)
  set StartFold_=C:\_D
  :: Run the VBS script with Microsoft Windows Script Host Version 5.6
  cscript //nologo "%temp%\tmp$$$.vbs"
  :: Clean up
  for %%f in ("%temp%\tmp$$$.vbs") do if exist %%f del %%f
  endlocal & goto :EOF

  Function NumberOfFilesInFolder(FolderName) 'VBS
    Dim fso, f, f1, fc, CountFiles 'VBS
    Set fso = CreateObject("Scripting.FileSystemObject") 'VBS
    Set f = fso.GetFolder(FolderName) 'VBS
    Set fc = f.Files 'VBS
    CountFiles = 0 'VBS
    For Each f1 in fc 'VBS
      CountFiles = CountFiles + 1 'VBS
    Next 'VBS
    NumberOfFilesInFolder = CountFiles 'VBS
  End Function 'VBS

  Function NumberOfFoldersInFolder(FolderName) 'VBS
    Dim fso, f, f1, fc, CountFolders 'VBS
    Set fso = CreateObject("Scripting.FileSystemObject") 'VBS
    Set f = fso.GetFolder(FolderName) 'VBS
    Set fc = f.SubFolders 'VBS
    CountFolders = 0 'VBS
    For Each f1 in fc 'VBS
      CountFolders = CountFolders + 1 'VBS
    Next 'VBS
    NumberOfFoldersInFolder = CountFolders 'VBS
  End Function 'VBS
 
  Function TraverseSubFolders(StartFolderName) 'VBS
    Dim fso, f, f1, sf, nFil, nFol 'VBS
    Set fso = CreateObject("Scripting.FileSystemObject") 'VBS
    Set f = fso.GetFolder(StartFolderName) 'VBS
    Set sf = f.SubFolders 'VBS
    For Each f1 in sf 'VBS
      nFil = NumberOfFilesInFolder(f1) 'VBS
      nFol = NumberOfFoldersInFolder(f1) 'VBS
      if (CLng(nFil) = 0) And (CLng(nFol) = 0) Then 'VBS
        Wscript.Echo f1 'VBS
      End If 'VBS
      TraverseSubFolders(f1) 'VBS
    Next 'VBS
  End Function 'VBS
 
  Function TraverseFolders(StartFolderName) 'VBS
    Dim fso, f, f1, sf, nFil, nFol 'VBS
    Set fso = CreateObject("Scripting.FileSystemObject") 'VBS
    If (fso.FolderExists(StartFolderName)) Then 'VBS
      Set f = fso.GetFolder(StartFolderName) 'VBS
      nFil = NumberOfFilesInFolder(f) 'VBS
      nFol = NumberOfFoldersInFolder(f) 'VBS
      If (CLng(nFil) = 0) And (CLng(nFol) = 0) Then 'VBS
        Wscript.Echo f 'VBS
      End If 'VBS
      TraverseSubFolders(f) 'VBS
    Else 'VBS
      Wscript.Echo "Folder " & StartFolderName & " not found" 'VBS
      Wscript.Quit 'VBS
    End If 'VBS
  End Function 'VBS

  Dim WshShell, StartAtFolder 'VBS
  Set WshShell = WScript.CreateObject("WScript.shell") 'VBS
  StartAtFolder = WshShell.ExpandEnvironmentStrings("%StartFold_%") 'VBS
  TraverseFolders StartAtFolder 'VBS

In pure CMD script one could try
  @echo off & setlocal enableextensions enabledelayedexpansion
  for /f "tokens=1 delims=" %%d in ('dir /s /b /a:d c:\_m') do (
    call :DirEmpty "%%d"
    if "!empty_!"=="true" echo %%d)
  endlocal & goto :EOF
  ::
  :: ======================================================

  :DirEmpty
  set empty_=true
  dir %1 /a 2>&1 | find "File(s)" | find /v " 0 File(s)" > nul
  if !errorlevel! EQU 0 set empty_=false
  dir %1 /a 2>&1 | find "Dir(s)" | find /v " 2 Dir(s)" > nul
  if !errorlevel! EQU 0 set empty_=false
  goto :EOF

However, the above will skip foldername which include an exlamation mark (!). Thus, alternatively
  @echo off & setlocal enableextensions disabledelayedexpansion
  for /f "tokens=1 delims=" %%d in ('dir /s /b /a:d c:\_m') do (
    call :DirEmpty "%%d")
  endlocal & goto :EOF
  ::
  :: ======================================================

  :DirEmpty
  set empty_=true
  dir %1 /a 2>&1 | find "File(s)" | find /v " 0 File(s)" > nul
  if %errorlevel% EQU 0 set empty_=false
  dir %1 /a 2>&1 | find "Dir(s)" | find /v " 2 Dir(s)" > nul
  if %errorlevel% EQU 0 set empty_=false
  if "%empty_%"=="true" echo %1
  goto :EOF

With slight adjustments on the inventive original formulation by Dean Wells in news: microsoft.public.win2000.cmdprompt.admin we can use
  @echo off & setlocal enableextensions
  dir "C:\MyFolder\*.*" /a /b^
    | find /v "SomeUnlikelyString">nul ^
      && echo NOT empty || echo Empty
  endlocal & goto :EOF
As a sideline, note the usage of the caret ^ for dividing a command structure over several lines to avoid wrapping problems in presenting a solution.

Another sideline, about || && and redirection:
foxidrive wrote:
  On Mon, 20 Nov 2006 19:14:42 +0200, Timo Salmi of a question made to him:
    setlocal enableextensions
    vol K: |find "48C4-AE69" && echo Backup Samsung || echo Backup Western Digital   %path_to_start%backup.log
    endlocal
  (Fails. Why?)
--- end of the forwarded quote ---

> I can confirm that adding redirection to such a line changes the
> behavior, and that enclosing the command in ( ) restores it.
> You can test it with these two lines.
>
> (echo b|find "a">nul && echo 0 ||echo 1) >a.txt
> (echo a|find "a">nul && echo 0 ||echo 1) >a.txt

Good catch. Some further trials show that same effect can be achieved by redirecting the output of the script outside it rather than within it. Thus the following also works
  @echo off & setlocal enableextensions
  rem C:\_D\TEST\CMDFAQ.CMD
  echo b|find "a">nul && echo yes|| echo no
  echo a|find "a">nul && echo yes|| echo no
  endlocal & goto :EOF

  C:\_D\TEST>CMDFAQ.CMD > a.txt
  The contents of a.txt will be
    no
    yes

References/Comments: (If a Google message link fails try the links within the brackets.)
  Google Groups May 17 2004, 12:30 am [M]
  hh ntcmds.chm::/ntcmds_shelloverview.htm