Gregor1806 Posted May 28, 2010 Share Posted May 28, 2010 Hi guys, OK, been trying to write a script that cleans up old MS hotfix extract folders. Not sure if this happens to anyone else, but sometimes we get leftover hotfix install folders scattered around the local disk with random names. When you try to delete these folders, you can't unless you take ownership of these and reflow the ACL perms. So the script I am trying to write, basically tries to automate this process using the SetACL.exe (downloaded here: http://setacl.sourceforge.net/) to reset the ACL perms, then perform a basic RD /S /Q to remove these unwanted folders. After searching the forum, I found GEOSoft's _Fldr_ListToArray() function and have tried to adapt it to suit my needs. Using GEOSoft's _Fldr_ListToArray() function, I search the drive for all folders, then exclude a list of known good folders, which then has the SetACL and RD /S /Q code run on it. It's mostly working, however GEOSoft's _Fldr_ListToArray() function contains a couple of Regular Expresssions which I'm having some difficulty in amending to suit my needs. So my problem really is a regex problem I think. What I want it to do is to always correctly exclude the folders from the known good folder list (this is read from a Config.INI file and will always be pre-determined). As you will see from my sample script below, I've tried various different regex attempts - but if the foldername in the exclude list includes any special characters, such as `£$%&#~ etc (all of which are valid as part of Windows file/folder names) it seems to ignore these and still attempt to delete them - even though they are supposed to be excluded. Here's my config.ini file with some sample exclude lists: [Settings] ;Drive letter with : and no \ Drive=C: ;Multiple folders must be separated with the | character and with no spaces Exclude=Apps|Documents and Settings|DRV|Program Files|Temp|Windows|T-_St%N@!œ$^&();#~`ª'{}[],.+=|123-Test4$| and here's my code: expandcollapse popup#Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_icon=my.ico #AutoIt3Wrapper_Res_Comment=Script to cleanup left-over hotfix extract folders #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #cs ---------------------------------------------------------------------------- AutoIt Version: 3.3.6.1 Author: Gregor1806 Script Function: Script to cleanup left-over hotfix extract folders Requires setACL.exe from http://setacl.sourceforge.net/ and Config.INI file in script folder #ce ---------------------------------------------------------------------------- ;Script Start ;Set AutoIt options AutoItSetOption("TrayIconDebug", 1); Show debug info in tray icon AutoItSetOption("WinTitleMatchMode", 2); 2 = Match any substring in title AutoItSetOption("TrayIconHide", 1); 0 = do not hide, 1 = hide tray icon ;Define Includes #Include <Array.au3> ;Set Variables ;$strDrvLetter = "C:" ;$strExcludeFldrs = "Apps|Documents and Settings|DRV|Program Files|Temp|Windows"; Multiple folders can be separated with the | character $strConfigFile = @ScriptDir & "\Config.INI" If Not FileExists($strConfigFile) Then MsgBox(0, "Error!", "Config file: " & $strConfigFile & " is missing." & @CRLF & "Please check file and re-try.") Exit EndIf $strDrvLetter=IniRead($strConfigFile, "Settings", "Drive", "") $strExcludeFldrs=IniRead($strConfigFile, "Settings", "Exclude", "") ;Main Script ;SetACL.exe downloaded from here: http://setacl.sourceforge.net/ FileInstall("SetACL.exe", @ScriptDir & "\setacl.exe", 1) ; Folders in C:\, non-recursive, excluding specified folders and including Hidden and System folders $aFolderList = _Fldr_ListToArray($strDrvLetter, $strExcludeFldrs, False) ;_ArrayDelete($aFolderList, 0) ;_ArrayDisplay($aFolderList, "Folders to Remove") $iMaxRows = UBound($aFolderList) ;Verify you have an array If IsArray($aFolderList) Then For $i = 0 to ($iMaxRows -1) ;Msgbox(0, "Info", $aFolderList[$i]) ;Exit if no folders found If $aFolderList[$i] = "" Then Msgbox(0, "Info", "No folders found") ExitLoop EndIf ;FileWriteLine(@ScriptDir & "\matches.txt", $aFolderList[$i]) ;#cs $strCMDLine = 'setacl.exe -on "' & $strDrvLetter & '\' & $aFolderList[$i] & '" -ot file -actn setowner -ownr n:Administrators -rec cont_obj' RunWait(@ComSpec & " /c " & $strCMDLine, @ScriptDir, @SW_HIDE); Reset ACLs Sleep(750); Pause for 3/4 of a second $strCMDLine = 'setacl.exe -on "' & $strDrvLetter & '\' & $aFolderList[$i] & '" -ot file -actn setprot -op "dacl:np;sacl:nc" -rec cont_obj -ot file -actn ace -ace "n:Administrators;p:full"' RunWait(@ComSpec & " /c " & $strCMDLine, @ScriptDir, @SW_HIDE); Reset ACLs Sleep(750); Pause for 3/4 of a second RunWait(@ComSpec & " /c " & 'RD /S /Q "'& $strDrvLetter & '\' & $aFolderList[$i] & '"', @ScriptDir, @SW_HIDE); Remove folders ;#ce Next Else MsgBox(0, "$aFolderList", "Is not an array - no folders found") EndIf Sleep(2000); Pause for 2 seconds If FileExists(@ScriptDir & "\setacl.exe") Then FileDelete(@ScriptDir & "\setacl.exe") ;*** Define Functions *** ;=============================================================================== ; Function Name: _Fldr_ListToArray() ; Description: Recursivly find the folders in a given path (returns full path for each) ; Syntax: _Fldr_ListToArray($s_Path[, $b_Recurse[, $b_Hidden[, $b_System]]]) ; Parameter(s): $s_Path - The base folder ; $s_Ignore - Pipe (|) separated list of folders to ignore. The * wildcard is accepted. ; $b_Recurse - If True (default) search is recursive ; $b_Hidden - If False (default) "Hidden" folders are NOT included ; $b_System If True (default) "System" folders are included. ; Requirements: ; Return Value(s): Success - A 0 based array of the folders with paths ; Failure - Sets @Error to 1 ; Author(s): George (GEOSoft) Gedye ; Notes: ;Example(s): #cs ;; folders in C:\, non-recursive Excluding the Windows folder and including Hidden and System folders $aArray = _Fldr_ListToArray("c:", "Windows", True) _ArrayDisplay($aArray) #ce ;=============================================================================== Func _Fldr_ListToArray($s_Path, $s_Ignore = "", $b_Recurse = True, $b_Hidden = False, $b_System = True) If StringRight($s_Path, 1) <> "\" Then $s_Path &= "\" $s_Path = '"' & $s_Path & '"' Local $s_Working = @WorkingDir, $s_Env = "" FileChangeDir(@TempDir) Local $sFile = "dir.txt" If FileExists($sFile) Then FileDelete($sFile) If $b_Recurse Then $s_Env &= " /s" $s_Env &= " /b /o:n" Local $s_Attrib = " /a:d" If NOT $b_Hidden Then $s_Attrib &= "-h" If NOT $b_System Then $s_Attrib &= "-s" $s_Env &= $s_Attrib EnvSet("DIRCMD", $s_Env) $hPID = Run(@ComSpec & ' /c dir ' & $s_Path & " > " & $sFile , "", @SW_HIDE, 0x02) While ProcessExists($hPID) If @error Then ExitLoop WEnd Local $s_Str = StringStripWS(FileRead($sFile), 2) FileDelete($sFile) EnvSet("DIRCMD", "") FileChangeDir($s_Working) If $s_Str Then ;MsgBox(0, "$s_Str1", $s_Str) If $s_Ignore Then $aIgnore = StringSplit($s_Ignore, "|", 2) For $i = 0 To UBound($aIgnore) -1 ;MsgBox(0, "$aIgnore["& $i & "]", $aIgnore[$i]) $aIgnore[$i] = StringRegExpReplace($aIgnore[$i], "\.*\*+", "\.\*\?") ;MsgBox(0, "$aIgnore["& $i & "]", $aIgnore[$i]) ; Orig: $s_Str = StringRegExpReplace($s_Str, "(?i)(?m:^).+\\" & $aIgnore[$i] & "\\.*(?:\z|\v)+", "") ;$s_Str = StringRegExpReplace($s_Str, "(?i).*?" & $aIgnore[$i] & ".*?", "") ; Works:$s_Str = StringRegExpReplace($s_Str, "(?i).*?" & $aIgnore[$i] & ".*(?:\z|\v)+|.*T-_St%N@!£\$\^&\(\);#~`¬'\{\}\[\],\.\+=", ""); & ".*(?:\z|\v)+" ;$s_Str = StringRegExpReplace($s_Str, "(?i).*?" & $aIgnore[$i] & ".*(?:\z|\v)+|.*T-_St%N@!£\$\^&\(\);#~`¬'\{\}\[\],\.\+=", ""); & ".*(?:\z|\v)+" ;Different:$s_Str = StringRegExpReplace($s_Str, "(?i)(?m:^).*?(\W" & $aIgnore[$i] & ").*(?:\z|\v)+", "") $s_Str = StringRegExpReplace($s_Str, "(?i)(?m:^).*?" & $aIgnore[$i] & ".*(?:\z|\v)+", "") ;$s_Str = StringRegExpReplace($s_Str, "(?i)" & $aIgnore[$i] & ".*(?:\z|\v)+", "") Next EndIf ;FileWriteLine(@ScriptDir & "\result.txt", $s_Str) ;MsgBox(0, "Folders to remove", $s_Str) $a_Fldrs = StringRegExp($s_Str, "(?i)(?m:^)(.+)(?:\v|$)+", 3) ;_ArrayDisplay($aIgnore, "Folders to ignore") ;MsgBox(0, "$s_Str", $s_Str) ;_ArrayDisplay($a_Fldrs) If Not @error Then For $i = 0 To UBound($a_Fldrs) -1 $a_Fldrs[$i] = StringStripWS($a_Fldrs[$i], 2) Next Return $a_Fldrs EndIf EndIf Return SetError(1) EndFunc ;;<===>_Fldr_ListToArray ;Script End If anyone can help me sort out the regex, then I think it will work correctly. Any help or advice is greatly appreciated! Many thanks, Gregor1806 Link to comment Share on other sites More sharing options...
GEOSoft Posted May 28, 2010 Share Posted May 28, 2010 (edited) What kind of filenames are you attenpting to exclude? remember you can use the Wildcards "*" and "?" only. Windows will read a tilde (~) as a wildcard in most cases but it won't work in this function. You would probably have to use something like FileGetLongName() if there is a Tilde in the path. EDIT: If you can, PM me the list of excluded folder names. I don't have time to check it today but I will in the next day or so. Also I'll have to look and see if that function is actually my latest version. Edited May 28, 2010 by GEOSoft George Question about decompiling code? Read the decompiling FAQ and don't bother posting the question in the forums.Be sure to read and follow the forum rules. -AKA the AutoIt Reading and Comprehension Skills test.*** The PCRE (Regular Expression) ToolKit for AutoIT - (Updated Oct 20, 2011 ver:3.0.1.13) - Please update your current version before filing any bug reports. The installer now includes both 32 and 64 bit versions. No change in version number. Visit my Blog .. currently not active but it will soon be resplendent with news and views. Also please remove any links you may have to my website. it is soon to be closed and replaced with something else. "Old age and treachery will always overcome youth and skill!" Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now