This script originated because of the following thread started by Enrica:
http://www.autohotkey.com/forum/viewtopic.php?t=3699
It searches for, lists, and deletes upon approval, all empty folders within a user-specified location. Folders do not go to the Recycle Bin.
Code:
; DeleteEmptyFolders Utility 1.3.1
; by Decarlo
!#e:: ; comment this line when using it for command line
; added support for commandline parameters and an auto-delete mode with logfile.
; with command line parameters, selectionEF corresponds to the first, and targetFolderEF to the second.
; note: sending function parameters thru a hotkey achieves a similar mode.
; streamlined the output code.
; added handling of Folders which contain only Empty Subfolders.***
; progress window: enabled dragging, added option to remove window (for faster run)
; detects if target folder doesnt exist, and handles if it is itself empty
; fixed initialization.
if 2 <> ; command-line parameters received
DeleteEmptyFolders()
else
{
selectionEF = ;1e ; input values here to bypass the Input prompt.
targetFolderEF = C:\ ; leave at least 1 param blank to show the Input prompt.
DeleteEmptyFolders()
}
return
DeleteEmptyFolders() ; use of local function vars avoids possible naming conflicts with common variables of other routines
{
SetFormat, Float, 0.3
global 0, 1, 2 ; recognize command-line parameters
global selectionEF, targetFolderEF
emptytargetFolderEF=
backSlashCheck=
Splash=
possibleEmptySubFoldersFolders=
countFoldersEmptySubFolders=0
emptySubfoldersFolderList=
countTopmostEmptyFolders=0
topmostEmptyFoldersList=
countFilesFolders=
countFolders=
countEmptyFolders=
emptyFolderList=
FileFolderList=
FolderList=
if 2 <>
{
selectionEF = %1%
targetFolderEF = %2%
}
else if ( selectionEF AND targetFolderEF ) ; function parameters received (from this same script)
1 := 1 ; this construct avoids the next Else (Input prompt) if the necessary values exist.
else
{
InputBox, selectionEF, DeleteEmptyFolders Utility, Please select:`n1. list/delete empty folders`n2. list/delete empty folders and list all folders`n3. list/delete empty folders and list all folders and files`nInclude A (capital) to auto-delete empty folders (caution). no progress window.`nInclude w to run without progress window (better speed).`nInclude e to also find folders containing only empty subfolders.`nThese parameters also apply to command-line mode.,, 700, 240,,,,, 1e
If (ErrorLevel<>0 OR selectionEF="")
EXIT
DEF_1 = Enter the complete path of the target folder.`nAll its empty folders will be listed and a prompt shown for approval to delete.`nFor long paths`, it is better to copy-paste from the AddressBar.
ifInString, selectionEF, 1
InputBox, targetFolderEF, DeleteEmptyFolders Utility, %DEF_1%,, 700, 170,,,,, C:\
else ifInString, selectionEF, 2
InputBox, targetFolderEF, DeleteEmptyFolders Utility, %DEF_1%`nAll subfolders of the target folder will also be listed.`n,, 700, 170,,,,, C:\
else ifInString, selectionEF, 3
InputBox, targetFolderEF, DeleteEmptyFolders Utility, %DEF_1%`nAll files and folders of the target folder will also be listed.`n,, 700, 170,,,,, C:\
If (ErrorLevel<>0 OR targetFolderEF="")
EXIT
}
StringCaseSense, on
ifInString, selectionEF, A
{
StringReplace, selectionEF, selectionEF, A, autoW
StringCaseSense, off
}
if selectionEF not contains 1,2,3 ; verify parameters
{
ifInString, selectionEF, auto
{
GoSub CreateLogName
FileAppend, selectionEF parameter did not contain 1, 2, or 3. Exiting., %logName%
}
else
msgbox,,, invalid parameter, .7
EXIT
}
ifNotInString, targetFolderEF, C:\
{
ifInString, selectionEF, auto
{
GoSub CreateLogName
FileAppend, %targetFolderEF% is an invalid targetFolderEF parameter. Exiting., %logName%
}
else
msgbox,,, invalid parameter, .7
EXIT
}
ifInString, selectionEF, 1
{
StringReplace, selectionEF, selectionEF, 2
StringReplace, selectionEF, selectionEF, 3
}
else ifInString, selectionEF, 2
StringReplace, selectionEF, selectionEF, 3
ifNotInString, selectionEF, w
Splash=1 ; only built-in cmds can be used on same line above
StringRight, backSlashCheck, targetFolderEF, 1
if backSlashCheck=\
StringTrimRight, targetFolderEF, targetFolderEF, 1
targetFolderEFLocation:=targetFolderEF . "\"
targetFolderEF:=targetFolderEF . "\*"
sleep 100 ; because splash doesnt appear sometimes
startTimeEmptyFolders=%A_TickCount%
IfExist, %targetFolderEFLocation%
Loop, %targetFolderEF%, 1, 1
{
if A_index=1
{
emptytargetFolderEF=N
if Splash=1
{
SplashTextOn, 500, 100, DeleteEmptyFolders Utility, Text
WinSet, AlwaysOnTop, off, DeleteEmptyFolders
WinSet, Enable,, DeleteEmptyFolders
}
ifInString, selectionEF, 3
GoSub DEF_SearchAll
else
GoSub DEF_SearchFolders
ifInString, selectionEF, e
GoSub DEF_FindEmptySubfoldersFolders
BREAK
}
}
else
{
ifInString, selectionEF, auto
{
GoSub CreateLogName
FileAppend, %targetFolderEFLocation% does not exist. Exiting., %logName%
}
else
msgbox, %targetFolderEFLocation%`n`ndoes not exist.
EXIT
}
endTimeEmptyFolders=%A_TickCount%
timeTaken:=(endTimeEmptyFolders-startTimeEmptyFolders)/1000.
SplashTextOff
ifInString, selectionEF, auto
GoSub DEF_Results_NoUserPrompt
else
GoSub DEF_Results
RETURN ; return from the function
DEF_FindEmptySubfoldersFolders:
;msgbox,,, searching only-empty-subfolders folders, .7
Loop, Parse, emptyFolderList, `n, `r ; use previous results: generate checklist
{
tracePathEmptyFolder = %A_LoopField%
Loop
{
if A_LoopField =
BREAK
StringLen, DEF_Length_1, tracePathEmptyFolder
StringGetPos, DEF_Loc1, tracePathEmptyFolder, \, R
if DEF_Loc1 = 2 ; path cannot be shorter than C:\
BREAK
StringTrimRight, tracePathEmptyFolder, tracePathEmptyFolder, % DEF_Length_1 - DEF_Loc1
ifInString, tracePathEmptyFolder, %targetFolderEFLocation% ; item must be in target folder
{
ifNotInString, possibleEmptySubFoldersFolders, %tracePathEmptyFolder%`r`n
{
possibleEmptySubFoldersFolders = %possibleEmptySubFoldersFolders%%tracePathEmptyFolder%`r`n
ControlSetText, Static1, %tracePathEmptyFolder%, DeleteEmptyFolders Utility
}
}
else BREAK
}
}
Sort, possibleEmptySubFoldersFolders, U
Loop, parse, possibleEmptySubFoldersFolders, `n, `r ; find all folders containing only empty subfolders
{
flagEmptyFolder = ; reset for each loop field
num=%A_Index%
Loop, %A_LoopField%\*, 0, 1 ; check files only, not folders
{
ControlSetText, Static1, %A_LoopFileFullPath%, DeleteEmptyFolders Utility
if A_Index = 1
{
flagEmptyFolder = N
BREAK
}
}
if flagEmptyFolder=
{
emptySubfoldersFolderList=%emptySubfoldersFolderList%%A_LoopField%`r`n
countFoldersEmptySubFolders+=1
}
}
; narrow the list: find topmost folders containing only empty subfolders (they contain all the items)
Loop, Parse, emptySubfoldersFolderList, `n, `r ; use previous results
{
if A_LoopField =
BREAK
tracePathEmptyFolder = %A_LoopField%
ControlSetText, Static1, %tracePathEmptyFolder%, DeleteEmptyFolders Utility
StringLen, DEF_Length_1, tracePathEmptyFolder
StringGetPos, DEF_Loc1, tracePathEmptyFolder, \, R
StringTrimRight, tracePathEmptyFolder, tracePathEmptyFolder, % DEF_Length_1 - DEF_Loc1
ControlSetText, Static1, %tracePathEmptyFolder%, DeleteEmptyFolders Utility
ifNotInString, emptySubfoldersFolderList, %tracePathEmptyFolder%`r`n
{
topmostEmptyFoldersList = %topmostEmptyFoldersList%%A_LoopField%`r`n
countTopmostEmptyFolders+=1
}
}
Sort, emptySubfoldersFolderList
Sort, topmostEmptyFoldersList, U
return
DEF_SearchAll:
Loop, %targetFolderEF%, 1, 1
{
FileFolderList=%FileFolderList%%A_LoopFileFullPath%`r`n
countFilesFolders+=1
countFolders+=1
flagEmptyFolder=
FileGetAttrib, Attribs, %A_LoopFileFullPath%
ifInString, Attribs, D
{
Loop, %A_LoopFileFullPath%\*, 1
{
ControlSetText, Static1, %A_LoopFileFullPath%, DeleteEmptyFolders Utility
if A_index=1
{
flagEmptyFolder=N
BREAK
}
}
if flagEmptyFolder=
{
emptyFolderList=%emptyFolderList%%A_LoopFileFullPath%`r`n
countEmptyFolders+=1
}
}
else countFolders-=1
}
return
DEF_SearchFolders:
Loop, %targetFolderEF%, 2, 1
{
ifInString, selectionEF, 2
FolderList=%FolderList%%A_LoopFileFullPath%`r`n
countFolders+=1
flagEmptyFolder=
Loop, %A_LoopFileFullPath%\*, 1
{
ControlSetText, Static1, %A_LoopFileFullPath%, DeleteEmptyFolders Utility
if A_index=1
{
flagEmptyFolder=N
BREAK
}
}
if flagEmptyFolder=
{
emptyFolderList=%emptyFolderList%%A_LoopFileFullPath%`r`n
countEmptyFolders+=1
}
; integrating the empty-subfolder search into this routine takes longer (almost 2x).
}
Sort, emptySubfoldersFolderList
return
DEF_EditorMsgStrings:
ifInString, selectionEF, e ; e = option to also find folders containing empty subfolders
{
DEF_EmpSub1 = %countFoldersEmptySubFolders% folders containing only empty subfolders also found.`r`n`r`n%countTopmostEmptyFolders% topmost folders containing only empty subfolders.`r`n`r`n
DEF_EmpSub2 = %countFoldersEmptySubFolders% Folders containing only empty subfolders:`r`n`r`n%emptySubfoldersFolderList%`r`n`r`n`r`n%countTopmostEmptyFolders% Topmost folders containing only empty subfolders:`r`n`r`n%topmostEmptyFoldersList%`r`n`r`n
}
else
{
DEF_EmpSub1 =
DEF_EmpSub2 =
}
DEF_1 = %DEF_TimeString%`r`n`r`n%countEmptyFolders% empty folders of %countFolders% total found inside %targetFolderEFLocation%`r`n`r`n%DEF_EmpSub1%time: %timeTaken% sec`r`n`r`n`r`n%countEmptyFolders% Folders without items:`r`n`r`n%emptyFolderList%`r`n`r`n`r`n%DEF_EmpSub2%---------------------------------`r`n`r`n
DEF_2 = The following folders could not be deleted:`r`n`r`n
ifInString, selectionEF, 1
DEF_msg=%DEF_1%%DEF_2%
else ifInString, selectionEF, 2
DEF_msg=%DEF_1%List of all %countFolders% subfolders:`r`n`r`n%FolderList%`r`n`r`n---------------------------------`r`n`r`n%DEF_2%
else
DEF_msg=%DEF_TimeString%`r`n`r`n%countEmptyFolders% empty folders of %countFilesFolders% total files/folders found inside %targetFolderEFLocation%`r`n`r`n%DEF_EmpSub1%total folders: %countFolders%`r`n`r`ntime: %timeTaken% sec`r`n`r`n`r`n%countEmptyFolders% Folders without items:`r`n`r`n%emptyFolderList%`r`n`r`n`r`n%DEF_EmpSub2%---------------------------------`r`n`r`nList of all %countFilesFolders% files/folders:`r`n`r`n%FileFolderList%`r`n`r`n---------------------------------`r`n`r`n%DEF_2%
return
CreateLogName:
Time := A_Now
StringTrimRight, Time, Time, 2
StringRight, HourMin, Time, 4
StringTrimRight, Time, Time, 4
Time := Time . "." . HourMin
logName := "logfile_DeleteEmptyFolders_" . Time ".txt"
return
DEF_Results_NoUserPrompt:
Sort emptyFolderList
Sort FolderList
Sort FileFolderList
GoSub CreateLogName
if countEmptyFolders=
{
if emptytargetFolderEF=
{
FileRemoveDir %targetFolderEFLocation%
FileAppend, %DEF_TimeString%`r`n`r`n%targetFolderEFLocation% is an empty folder. Deleted., %logName%
}
else ifInString, selectionEF, 1
FileAppend, %DEF_TimeString%`r`n`r`nNo empty folders were found in %targetFolderEFLocation%., %logName%
else
{
DEF_1 = %DEF_TimeString%`r`n`r`n0 empty folders of
DEF_2 = found inside %targetFolderEFLocation%`r`n`r`n
DEF_3 = time: %timeTaken% sec`r`n`r`n%emptyFolderList%`r`n`r`n---------------------------------`r`n`r`nList of all%A_Space%
ifInString, selectionEF, 2
DEF_msg=%DEF_1%%countFolders% total %DEF_2%%DEF_3%%countFolders% subfolders:`r`n`r`n%FolderList%`r`n
else
DEF_msg=%DEF_1%%countFilesFolders% total files/folders %DEF_2%total folders: %countFolders%`r`n`r`n%DEF_3%%countFilesFolders% files/folders:`r`n`r`n%FileFolderList%`r`n
FileAppend, %DEF_msg%, %logName%
}
}
else
{
GoSub DEF_EditorMsgStrings
FileAppend, %DEF_msg%, %logName%
listToDelete = %emptyFolderList%
GoSub DeleteEmpty_NoUserPrompt
if countFoldersEmptySubFolders
{
DEF_1 = 1
listToDelete = %topmostEmptyFoldersList%
GoSub DeleteEmpty_NoUserPrompt
}
}
return
DeleteEmpty_NoUserPrompt:
errorList=
errorsOccurred=
Loop, Parse, listToDelete, `n, `r
{
if A_LoopField=
BREAK
FileRemoveDir, %A_LoopField%, 1 ; recurse to remove empty subfolders
if ErrorLevel=1
{
errorList=%errorList%%A_LoopField%`r`n
errorsOccurred=1
}
}
if errorsOccurred=1
FileAppend, %errorList%, %logName%
else
{
if DEF_1 = 1
FileAppend, of folders containing only empty subfolders:`n<none>`n`n, %logName%
else
FileAppend, of folders without items:`n<none>`n`n, %logName%
}
return ; end of auto-delete section
;-------------------------------------------
DEF_Results:
Sort emptyFolderList
Sort FolderList
Sort FileFolderList
if countEmptyFolders=
{
if emptytargetFolderEF=
{
msgbox, 4097, DeleteEmptyFolders Utility, %targetFolderEFLocation%`n`nis an empty folder.`n`nDelete it?
ifMsgBox, OK
FileRemoveDir %targetFolderEFLocation%
}
else ifInString, selectionEF, 1
msgbox, No empty folders were found inside`n`n%targetFolderEFLocation%
else
{
Run, notepad,,, Npid
WinActivate, ahk_pid %Npid%
WinWaitActive, ahk_pid %Npid%
FormatTime, DEF_TimeString
DEF_1 = %DEF_TimeString%`r`n`r`n0 empty folders of
DEF_2 = found inside %targetFolderEFLocation%`r`n`r`n
DEF_3 = time: %timeTaken% sec`r`n`r`n%emptyFolderList%`r`n`r`n---------------------------------`r`n`r`nList of all%A_Space%
ifInString, selectionEF, 2
DEF_msg=%DEF_1%%countFolders% total %DEF_2%%DEF_3%%countFolders% subfolders:`r`n`r`n%FolderList%`r`n
else
DEF_msg=%DEF_1%%countFilesFolders% total files/folders %DEF_2%total folders: %countFolders%`r`n`r`n%DEF_3%%countFilesFolders% files/folders:`r`n`r`n%FileFolderList%`r`n
ControlSetText, Edit1, %DEF_msg%, ahk_pid %Npid%
DEF_1 = found inside`n`n`t%targetFolderEFLocation%`n`n
ifInString, selectionEF, 2
msgbox, 4097, DeleteEmptyFolders Utility, 0 empty folders of %countFolders% total were %DEF_1%time: %timeTaken% sec`n`n
else
msgbox, 4097, DeleteEmptyFolders Utility, 0 empty folders of %countFilesFolders% total files/folders were %DEF_1%total folders: %countFolders%`n`ntime: %timeTaken% sec`n`n
}
}
else
{
Run, notepad,,, Npid
WinActivate, ahk_pid %Npid%
WinWaitActive, ahk_pid %Npid%
FormatTime, DEF_TimeString
GoSub DEF_EditorMsgStrings
ControlSetText, Edit1, %DEF_msg%, ahk_pid %Npid%
DEF_1 = %countEmptyFolders% empty folders of%A_Space%
DEF_2 = were found inside`n`n`t%targetFolderEFLocation%`n`n%DEF_EmpSub1%
DEF_3 = time: %timeTaken% sec`n`nKeep in mind that some empty folders might be `nused by the operating system, anti-virus, firewall, `nand various utilities, and even spyware.`n`nSave the log in case you are not sure what you are deleting.`n`n`nDo you wish to delete the %countEmptyFolders% empty folders?`n`nThe recycle bin will be bypassed.`n`nhold Ctrl Shift with OK to delete.`n
ifInString, selectionEF, 3
msgbox, 4097, DeleteEmptyFolders Utility, %DEF_1%%countFilesFolders% total files/folders %DEF_2%total folders: %countFolders%`n`n%DEF_3%
else
msgbox, 4097, DeleteEmptyFolders Utility, %DEF_1%%countFolders% total %DEF_2%%DEF_3%
ifMsgBox, OK
{
if ( GetKeyState("Ctrl","p") AND GetKeyState("Shift","p") )
{
listToDelete = %emptyFolderList%
GoSub DeleteEmpty
if countFoldersEmptySubFolders
{
msgbox, 4097,, %countFoldersEmptySubFolders% folders containing only empty subfolders.`n`n%countTopmostEmptyFolders% topmost folders containing only empty subfolders.`n`n`n`nDo you wish to delete the %countTopmostEmptyFolders% topmost folders?`n`nThis will delete all %countFoldersEmptySubFolders% folders containing only empty subfolders.`n`nThe recycle bin will be bypassed.`n`nhold Ctrl Shift with OK to delete.`n
ifMsgBox, OK
if ( GetKeyState("Ctrl","p") AND GetKeyState("Shift","p") )
{
DEF_1 = 1
listToDelete = %topmostEmptyFoldersList%
GoSub DeleteEmpty
}
}
}
}
}
return
DeleteEmpty:
errorList=
errorsOccurred=
;SplashTextOn, 500, 100, DeleteEmptyFolders Utility, now deleting: ---
;WinSet, AlwaysOnTop, Off, DeleteEmptyFolders Utility
Loop, Parse, listToDelete, `n, `r
{
if A_LoopField=
BREAK
; ControlSetText, Static1, now deleting item %A_Index%:`n%A_LoopField%, DeleteEmptyFolders Utility
FileRemoveDir, %A_LoopField%, 1 ; recurse to remove empty subfolders
if ErrorLevel=1
{
errorList=%errorList%%A_LoopField%`r`n
errorsOccurred=1
msgbox error deleting %A_LoopField%`n`nerrorList=`n`n%errorList%
}
}
;SplashTextOff
if errorsOccurred=1
{
ControlSend, Edit1, ^{end}, ahk_pid %Npid%
Control, EditPaste, %errorList%, Edit1, ahk_pid %Npid%
msgbox The following empty folders could not be deleted:`n`n%errorList%
}
else
{
if DEF_1 = 1
{
ControlSend, Edit1, ^{end}of folders containing only empty subfolders:`n<none>`n`n, ahk_pid %Npid%
msgbox %countEmptyFolders% folders containing only empty subfolders`n`nsuccessfully deleted.
}
else
{
ControlSend, Edit1, ^{end}of folders without items:`n<none>`n`n, ahk_pid %Npid%
msgbox %countEmptyFolders% folders without items`n`nsuccessfully deleted. ; msgbox may interfere with deletion
}
}
return ; for GoSub. main return is at the top of function.
} ;--------------------------- end function
;-------------------------------------------------------