Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

Remove empty subdirectories with GUI and history


  • Please log in to reply
1 reply to this topic
Laszlo
  • Moderators
  • 4713 posts
  • Last active: Mar 31 2012 03:17 AM
  • Joined: 14 Feb 2005
A decent user interface is longer than the core empty directory removing function, which was discussed in another thread. In this case, it is almost 40 lines, but it offers a lot of functionality:

The cleaned up folders are kept in a history file, the most recently used one is at first. When the program starts, it reads this file, and shows the files chosen in the past in a combo box. The most recent one is selected. If the user wants to clean another directory, he can select it form a folder selection dialog box (activated by the Select Dir button or by Alt-S), or he can type-in the name of the folder either in this dialog or directly into the combo box. If he changes his mind, closing the GUI (Esc, clicking on [x], Alt-X or clicking the Exit button) exits the program.

If the user clicks on the OK button (or presses Alt-O) the directory shown in the combo box is cleaned, that is, its empty directories are offered to be removed. But before the work starts, the chosen directory is checked if it exists, and a possible trailing \ is removed. At the end the program terminates.

This version of the DelEmpty function shows the name of the currently processed directory in a TrayTip, so the user knows where the directory traversal is at any moment. When an empty subdirectory is found, the user is asked if he wants it to be deleted. If yes, the empty directory is removed, otherwise it stays as it was before. Some statistics is also collected: the number of subdirectories, the number of removed ones and the number of kept empty subdirectories. At the end this information is shown in a message box.
HistoryFile =  %A_ScriptDir%\Del0Dir.hst
FileRead history, %HistoryFile%

Start:
Gui Add, ComboBox, y12 w265 vdir, %history%
Gui Add, Button, y+10 w75, &Select Dir
Gui Add, Button, x+20 w75, &OK
Gui Add, Button, x+20 w75, E&xit
Gui Show,,Dir to clean
GuiControl Choose, dir, 1
return

ButtonOK:
   Gui Submit
   StringRight c, dir, 1
   ifEqual c,\, StringTrimRight dir, dir, 1  ; remove trailing \
   FileGetAttrib Attrib, %dir%
   If Attrib not contains D
   {
      MsgBox Invalid directory
      Gui Show
      Return
   }
   StringReplace history, history, %dir%|,,All
   history = %dir%|%history%
   FileDelete %HistoryFile%
   FileAppend %history%, %HistoryFile%

   DelEmpty(dir)
   TrayTip

   MsgBox Number of subdirectories = %total%`nDeleted empty directories = %deleted%`nKept empty directories = %kept%
ButtonExit:
GuiClose:
GuiEscape:
ExitApp

ButtonSelectDir:
   Gui +OwnDialogs
   FileSelectFolder d, *C:\, 2, Select a directory to clean
   IfEqual d,, Return
   GuiControl Text, dir, %d%
Return

DelEmpty(dir)
{
   Global total, deleted, kept
   total += 1
   FileGetAttrib Attrib,  %dir%
   FileGetTime ModTime,   %dir%, M
   FileGetTime CreateTime,%dir%, C

   Loop %dir%\*.*, 2
      DelEmpty(A_LoopFileFullPath)

   TrayTip,,%dir%
   FileRemoveDir %dir%
   IfEqual ErrorLevel,1, Return
   deleted += 1
   MsgBox 4,,Remove directory %dir%?`nCreated:  %CreateTime%`nModified: %ModTime%
   IfMsgBox Yes
      Return
   kept += 1
   deleted -= 1
   FileCreateDir %dir%
   FileSetAttrib +%Attrib%, %dir%
   FileSetTime %CreateTime%,%dir%, C
   FileSetTime %ModTime%,   %dir%, M
}
50 lines containing AHK commands are much more than needed for this task. As seen in the other thread, the 7 lines below will do for most of us, the rest of the code just makes the script fancy.
DelEmpty("C:\backup") 

DelEmpty(dir) 
{ 
   Loop %dir%\*.*, 2 
      DelEmpty(A_LoopFileFullPath) 
   FileRemoveDir %dir% 
}


Laszlo
  • Moderators
  • 4713 posts
  • Last active: Mar 31 2012 03:17 AM
  • Joined: 14 Feb 2005
As always, there is no limit of what can be added to a script. Here is a commented version with the option to ignore (keep) directories with any of the specified attribute: R = Read-only, S = System, H = Hidden. The desired keep-attributes can be checked in the main GUI. Also, the cleaning is restarted after an empty subdirectory removal, with asking for another directory name to be cleaned. You have to explicitly exit the script if it was enough.
HistoryFile = %A_ScriptDir%\Del0Dir.hst      ; storage for cleaned directories

FileRead history, %HistoryFile%



Start:

total =  0

deleted= 0                                   ; reset statistics

kept =   0

Gui Add, ComboBox, x5 y14 w265 vdir, %history%

Gui Add, Button, x5 y+13 w75, &Select Dir

Gui Add, Button, x+20 w75, &OK

Gui Add, Button, x+20 w75, E&xit

Gui Add, GroupBox, x275 y2 w40 h80, Keep

Gui Add, Checkbox, x285 y20 vR, R

Gui Add, Checkbox, x285 y+4 vS, S

Gui Add, Checkbox, x285 y+4 vH, H

Gui Show,,Dir to clean

GuiControl Choose, dir, 1                    ; pre-select last used directory

return



ButtonOK:                                    ; run the cleaning

   Gui Submit                                ; assign value to dir

   IfEqual R,1, SetEnv R, R

   IfEqual S,1, SetEnv S, S

   IfEqual H,1, SetEnv H, H

   RSH = %R%,%S%,%H%                         ; keep dir with this attribute

   StringReplace RSH, RSH, 0,,All



   StringRight c, dir, 1

   ifEqual c,\, StringTrimRight dir, dir, 1  ; remove occasional trailing \

   FileGetAttrib Attrib, %dir%

   If Attrib not contains D                  ; is dir a directory?

   {

      MsgBox Invalid directory               ; if not: tell user

      Gui Show                               ; show old GUI again

      Return

   }

   StringReplace history,history,%dir%|,,All ; remove repetition

   history = %dir%|%history%                 ; prepend chosen dir

   FileDelete %HistoryFile%

   FileAppend %history%, %HistoryFile%       ; save history



   DelEmpty(dir)                             ; do the work

   TrayTip                                   ; remove last traytip



   MsgBox,                                   ; show statistics

(  LTRIM

   Cleaned directory = %dir%

   Number of subdirectories = %total%

   Deleted empty directories = %deleted%

   Kept empty directories = %kept%

)

   Gui Destroy                               ; for a fresh start

GoTo Start                                   ; RESTART for further directories



ButtonExit:

GuiClose:                                    ; EXIT

GuiEscape:

ExitApp



ButtonSelectDir:                             ; folder select dialog

   Gui +OwnDialogs                           ; must complete before return to main GUI

   FileSelectFolder d, *C:\, 2, Select a directory to clean

   IfEqual d,, Return                        ; return at cancelled dialog

   GuiControl Text, dir, %d%                 ; put dir in edit box

Return



DelEmpty(dir)                                ; the main function

{

   Global total, deleted, kept, RSH          ; variables for statistics, exclusion

   total += 1

   FileGetAttrib Attrib,  %dir%              ; get directory properties

   if Attrib contains %RSH%

      Return

   FileGetTime ModTime,   %dir%, M           ; time, for re-create

   FileGetTime CreateTime,%dir%, C



   Loop %dir%\*.*, 2                         ; try every child directory

      DelEmpty(A_LoopFileFullPath)           ; clean recursively



   TrayTip,,%dir%                            ; show processed directory

   FileRemoveDir %dir%                       ; remove dir if empty

   IfEqual ErrorLevel,1, Return              ; go on if not empty

   MsgBox 4,,Remove directory?`n%dir%`nCreated:  %CreateTime%`nModified: %ModTime%

   IfMsgBox Yes

   {                                         ; it is already removed

      deleted += 1                           ; increment count

      Return

   }

   FileCreateDir %dir%                       ; if user keeps dir: re-create

   kept += 1                                 ; count

   FileSetAttrib +%Attrib%, %dir%

   FileSetTime %CreateTime%,%dir%, C         ; re-set properties

   FileSetTime %ModTime%,   %dir%, M

}
If you like bloating the code further, you could save the keep-attributes in the history file together with the corresponding directory names. We can specify if AND or OR is to be used with the attributes. There could be a function to edit the history (most importantly deleting wrong entries). We could specify creation or access time ranges of subdirectories to keep, or exclude/include subdirectories by their names, and these lists of names could be also stored in the history next to the starting directory cleaned. We could specify if the subdirectories of a kept directory should be excluded from the search or only itself. (This would need some deeper changes in the code. Now, if the keep-attributes require, the complete subdirectory is excluded from the search, but user permission is only asked for, after all the empty sub-subdirectories have been removed already.)