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