Warning: Many of these scripts require additional files which will be included in the download.
Executing these scripts without those files could result in anything from minor irritations to code failure.
Be sure to download the zip file if you plan on using the code.

   Folder.au3

Last modified:   Wednesday, September 30, 2020

;*******************************************************************************
;
;   Function List
;         _Fldr_GetLevel()
;         _Fldr_GetParent()
;         _FldrCompression()
;         _FldrCopyMove()
;         _FldrGetDates()
;         _FldrGetSize()
;         _FldrListToArray()
;
;*******************************************************************************

;*******************************************************************************
; Constants for Special Folders in Windows

Global Const $Administrative_Tools = 0x2f
Global Const $All_Users_Application_Data = 0x23
Global Const $All_Users_Desktop = 0x19
Global Const $All_Users_Favorites = 0x19
Global Const $All_Users_Programs = 0x17
Global Const $All_Users_Start_Menu = 0x16
Global Const $All_Users_Startup = 0x18
Global Const $All_Users_Templates = 0x2e
Global Const $Application_Data = 0x1a
Global Const $CD_Burning_Folder = 0x003b
Global Const $Common_Files = 0x2b
Global Const $Control_Panel = 0x3
Global Const $Cookies = 0x21
Global Const $Desktop = 0x10
Global Const $Favorites = 0x6
Global Const $Fonts = 0x14
Global Const $Internet_Explorer = 0x1
Global Const $Local_Settings_Application_Data = 0x1c
Global Const $Local_Settings_History = 0x22
Global Const $Local_Settings_Temporary_Internet_Files = 0x20
Global Const $My_Computer = 0x11
Global Const $My_Documents = 0x5
Global Const $My_Music = 0xd
Global Const $My_Network_Places = 0x12
Global Const $My_Pictures = 0x27
Global Const $My_Recent_Documents = 0x8
Global Const $My_Videos = 0xe
Global Const $NetHood = 0x13
Global Const $Network_Connections = 0x31
Global Const $Printers_and_Faxes = 0x4
Global Const $PrintHood = 0x1b
Global Const $Program_Files = 0x26
Global Const $Programs = 0x2
Global Const $Recycle_Bin = 0xa
Global Const $SendTo = 0x9
Global Const $Start_Menu = 0xb
Global Const $Startup = 0x7
Global Const $System32 = 0x25
Global Const $Templates = 0x15
Global Const $User_Profile = 0x28
Global Const $Windows = 0x24
;*******************************************************************************

;*******************************************************************************
; Example(s)
#cs
    _Special_Folders($My_Network_Places)

    Func _Special_Folders ($Folder)
        $objShell = ObjCreate("Shell.Application")
        $objShell.open($objShell.NameSpace($Folder))
    EndFunc
#ce
;*******************************************************************************
#include-once
;;<<<<<<<<<<<<<<  Functions to assist with folder data management  >>>>>>>>>>>>>>>>>>>>>>>>>>>>

;===============================================================================
; Function Name:    _Fldr_GetLevel()
; Description:      Get the path to the parent of the specified folder
; Syntax:           _Fldr_GetLevel($sPath [, Level])
; Parameter(s):     $sFldr - The folder to start from
;                   $Level - How many levels to go up from $sFldr  Default is 1 which returns the same as
;                            _Fldr_GetParent() below
; Requirements:
; Return Value(s):  Success - Returns the path to the folder without a trailing backslash
;                   Failure Sets @Error
;                       [1 - Recursion level exceeded - Returns a blank string and sets @Error to 1
;                       [2 - $sPath does not exist - Returns a blank string and sets @Error to 2
; Author(s):        George (GEOSoft) Gedye
; Notes:
; Modifications:
; Example(s):     _Fldr_GetLevel("C:\WINDOWS\system32\SoftwareDistribution\Setup", 3) returns "C:\Windows"
;===============================================================================

Func _Fldr_GetLevel($sPath, $Level = 1);;  default $level takes it to the parent
If StringRight($sPath, 1) = "\" Then $sPath = StringTrimRight($sPath, 1)
If NOT FileExists($sPath) Then Return SetError(2, 2, "The starting folder does not exist")
Local $rFldr = StringSplit($sPath, "\"), $I, $fPath = ""
If $Level > Ubound($rFldr) -1 Then Return SetError(1, 1, "Recursion level exceeded");; Returns a blank string and sets @Error to 1
$Level += 1
For $I = 1 To Ubound($rFldr) - $Level
   $fPath &= $rFldr[$I] & "\"
Next
Return StringTrimRight($fPath, 1)
EndFunc    ;<===> _Fldr_GetLevel()

;===============================================================================
; Function Name:    _Fldr_GetParent()
; Description:      Get the path to the parent of the specified folder
; Syntax:           _FldrGetParent([$rFldr])
; Parameter(s):     $rFldr - The folder to query 
; Requirements:
; Return Value(s):  Success - Returns the path to the parent folder without a trailing backslash
;                   Failure Sets @Error
;                             [1 - unable to create the object
;                             [2 - $rFldr does not exist
; Author(s):        George (GEOSoft) Gedye
; Notes:
; Modifications:
;===============================================================================

Func _Fldr_GetParent($sFldr)
   If StringRight($sFldr, 1) = "\" Then $sFldr = StringTrimRight($sFldr, 1)
   Return StringLeft($sFldr, StringInStr($sFldr, "\", 0, -1) -1)
EndFunc    ;<===> _Fldr_GetParent()

;===============================================================================
; Function Name:   _Fldr_IsEmpty()
; Description:     Determine if a folder is empty
; Syntax:          _Fldr_IsEmpty("folder path")
; Parameter(s):    $szRoot - Path to the folder
; Requirement(s):   
; Return Value(s): 1 - the folder is empty
;                  0 - the folder contains files or folders (not empty)
; Author(s):   George (GEOSoft) Gedye
; Modification(s): 
; Note(s):    
; Example(s):   
;===============================================================================

Func _Fldr_IsEmpty($szRoot)
   If StringRight($szRoot, 1) <>"\" THen $szRoot &= "\"
   If FileFindFirstFile($szRoot & "*") = -1 Then Return 1
   Return 0
EndFunc   ;<==> _Fldr_IsEmpty()

;===============================================================================
; Function Name:    _FldrCompression()
; Description:      Compress or decompress a folder.
; Syntax:           _FldrCompression($rFldr [, $action])
; Parameter(s):     $rFldr - The folder to perform the action on.
;                   $action - Action to perform -- 0 = Compress (default), 1 = Decompress
; Requirements:
; Return Value(s):  Success - Compresses or Decompresses the specified folder
;                   Failure Sets @Error
;                      [1 - The current attributes of the folder match the requested action.
;                      [2 - $rFldr does not exist
;                      [3 - Invalid action specified. MUST be 1 or 0
; Author(s):        George (GEOSoft) Gedye
; Notes:
; Modifications:
; Example(s):
;                   $Cpr = _FldrCompression("C:\Test") ;; Compress the folder C:\Test
;                   If @Error Then MsgBox(0, 'Error', $Cpr)
;                   $Cpr = _FldrCompression("C:\Test", 1) ;; Decompress the folder C:\Test
;                   If @Error Then MsgBox(0, 'Error', $Cpr)
;===============================================================================

Func _FldrCompression($rFldr, $action= 0)
   Local $eMsg = 'The folder' & @CRLF & $rFldr & @CRLF & 'is already '
   If NOT FileExists($rFldr) Then Return SetError( 2, 2, 'Unable to locate the folder' & @CRLF & @CRLF & $rFldr)
   If $action = 0 Then
      If StringInStr(FileGetAttrib($rFldr), 'C') Then Return SetError( 1, 1, $eMsg & 'compressed')
   ElseIf $action = 1 Then
      If NOT StringInStr(FileGetAttrib($rFldr), 'C') Then Return SetError( 1, 1, $eMsg & 'uncompressed')
   Else
      Return SetError(3, 3, 'Invalid action')
   EndIf
   If NOT StringInStr($rFldr, '\\') Then $rFldr = StringReplace($rFldr, '\', '\\')
   $rFldr = Chr(39) & $rFldr & Chr(39)
   $objWMIService = ObjGet("winmgmts:" & "{impersonationLevel=impersonate}!\\.\root\cimv2")
   $colFolders = $objWMIService.ExecQuery ("Select * from Win32_Directory where name = " & $rFldr)
   For $objFolder in $colFolders
      If $action = 0 Then
         $errResults = $objFolder.Compress
      Else
         $errResults = $objFolder.UnCompress
      EndIf
   Next
EndFunc   ;<==> _FldrCompression()

;===============================================================================
; Function Name:    _FldrCopyMove()
; Description:      Copy or Move folders with progress dialog
; Syntax:           _FldrCopyMove(Folder to process, Destination folder[, Action])
; Parameter(s):     $rFldr - The full path of the folder to copy or move
;                   $nFldr - The full path of the destination folder
;                   $action - The action to perform 0 = Copy (default) 1 = Move
; Requirements:
; Return Value(s):  Success - Folder is copied / moved
;                   Failure Sets @Error
;                                [1 - unable to create the shell object
;                                [2 - the specified $rFldr was not located (check the path)
;                                [3 - an invalid action was specified
; Author(s):        George (GEOSoft) Gedye
; Notes:            To self --- removed all the dircopy's and used dircreate/filecopy
;                         and over a network it's 800 x's faster for large folder structures
; Modifications:
;===============================================================================

Func _FldrCopyMove($rFldr, $nFldr, $action = 0)
   If NOT FileExists($rFldr) Then Return SetError( 2, 2, 'Unable to locate the folder' & @CRLF & @CRLF & $rFldr)
   If $action <> 0 AND $action <> 1 Then Return SetError(3, 3, 'Invalid action')
   $obj = ObjCreate ("Shell.Application")
   If IsObj($obj) Then
      If NOT FileExists($nFldr) Then DirCreate($nFldr)
      $cFldr = $obj.NameSpace ($nFldr)
      If $action = 0 Then
         $cFldr.CopyHere ($rFldr, "&H0&")
      Else
         $cFldr.MoveHere ($rFldr, "&H0&")
      EndIf
   Else
      Return SetError(1, 1, 'Unable to create the Shell object')
   EndIf
EndFunc    ;<===> _FldrCopyMove()

;===============================================================================
; Function Name:    _FldrGetDates()
; Description:      Returns the Created, LastModified and LastAccessed dates and times of a folder as an array.
; Syntax:           _FldrGetDates([$rFldr [, $Mth_AsText [, $Ext_Date [, $T_Txt ]]]])
; Parameter(s):     $rFldr - The folder to query (default is current dir)
;                   $Mth_AsText - Return the month as text (default) Use 0 to return the numeric date
;                   $Ext_Date - If 0 returns the raw date.
;                               If 1 (default) returns a formatted date string
;                   $T_Txt - If set to 1 (default) and the date = current day then replaces the date with "Today at"
; Requirements:
; Return Value(s):  Success - Returns an Array containing the dates and times of the folder where
;                   array[1] = DateCreated
;                   array[2] = DateLastModified
;                   array[3] = DateLastAccessed
;                   Failure Sets @Error
;                                [1 - unable to create the FileSystem object
;                                [2 - $rFldr does not exist
; Author(s):        George (GEOSoft) Gedye
; Notes:
; Modifications:
;===============================================================================

Func _FldrGetDates($rFldr = '', $Mth_AsText = 1, $Ext_Date = 1, $T_Txt = 1)
   If $rFldr <> '' AND NOT FileExists($rFldr) Then Return SetError( 2, 2, 'Unable to locate the folder' & @CRLF & @CRLF & $rFldr)
   $obj = ObjCreate("Scripting.FileSystemObject")
   If IsObj($obj) Then
      If $rFldr = '' Then $rFldr = @HomeDrive & '\' & @HomePath
      $oFldr = $obj.GetFolder($rFldr)
      Local $Rtn = ''
      With $oFldr
         Dim $F_prop[3] = [.DateCreated,.DateLastModified,.DateLastAccessed]

         For $I = 0 To Ubound($F_Prop) -1
            $Rtn &= _FldrDate($F_Prop[$I], $Mth_AsText, $Ext_Date, $T_Txt) & '|'
         Next

      EndWith
      Return StringSplit(StringTrimRight($Rtn,1), '|')
   Else
      Return SetError(1, 1, 'Unable to create the FileSystem object')
   EndIf
EndFunc    ;<===> _FldrGetDates()

;===============================================================================
; Function Name:    _FldrGetSize()
; Description:      A replacement for the DirGetSize() function that will return the size as bytes, Kbs or Mbs
; Syntax:           _FldrGetSize([$rFldr [,$Set_Ext ]])
; Parameter(s):     $rFldr - The folder to query (default is current dir)
;                   $Set_Ext - If 1 (default) returns the size as shown in the description.
;                              If 0 then returns the same as DirGetSize()
; Requirements:
; Return Value(s):  Success the date as defined by $Set_Ext
;                   Failure Sets @Error
;                              [1 - unable to create the object
;                              [2 - $rFldr does not exist
; Author(s):        George (GEOSoft) Gedye
; Notes:
; Modifications:
;===============================================================================

Func _FldrGetSize($rFldr = '', $Set_Ext = 1)
   If $rFldr <> '' AND NOT FileExists($rFldr) Then Return SetError( 2, 2, 'Unable to locate the folder' & @CRLF & @CRLF & $rFldr)
   $obj = ObjCreate("Scripting.FileSystemObject")
   If IsObj($obj) Then
      If $rFldr = '' Then $rFldr = @HomeDrive & '\' & @HomePath
      $oFldr = $obj.GetFolder($rFldr)
      $F_Size = $oFldr.size
      If $Set_Ext <> 1 Then Return $F_Size
      $Div = 0

      While $F_Size > 1024
         $F_Size = $F_Size / 1024
         $Div += 1
      Wend

      If $Div = 0 Then
         Return $F_Size & ' bytes'
      ElseIf $Div = 1 Then
         Return Round($F_Size, 3) & ' Kb'
      EndIf
      Return Round($F_Size, 2) & ' Mb'
   Else
      Return SetError(1, 1, 'Unable to create the FileSystem object')
   EndIf
EndFunc    ;<===> _FldrGetSize()

;===============================================================================
; Function Name:    _FldrListToArray()
; Description:      Recursivly find the folders in a given path (returns full path for each)
; Syntax:           _FldrListToArray($szRoot, $nFlag = 1 )
; Parameter(s):     $szRoot - The base folder
;                   $sIgnore - Folders to exclude - MUST be pipe (|) separated
;                   $iRecurs - If 1 (default) search is recursive
;                   $iNoRoot - If 0 (default) $szRoot is included in the returned array
;                                    else $szRoot is ignored.
; Requirements:
; Return Value(s):  Success - A 1 based array of the folders with paths
;                   Failure - None
; Author(s):        George (GEOSoft) Gedye
; Notes:
;Example(s):
#cs
    #include <array.au3>
    ;; folders in C:\, ignore Windows and Recycler folders, recursive and don't include the root folder
    $aArray = _FldrListToArray("c:", "windows|recycler", 1, 1)
    _ArrayDisplay($aArray)
#ce
;===============================================================================

Func _FldrListToArray($szRoot, $sIgnore = "", $iRecurs = 1, $iNoRoot = 0 )
   If StringRight($szRoot, 1) <> '\' Then $szRoot &= '\'
   Local $szReturn = '',  $szBuffer = '', $szPathlist = '*', $oRoot = $szRoot & '*', $sChk = $szRoot
      $Hfile = FileFindFirstFile ($szRoot &'*')
      If $Hfile >= 0 Then
         $szBuffer = FileFindNextFile ($Hfile)
         While NOT @Error
            If StringInStr(FileGetAttrib($szRoot & $szBuffer), 'D') Then
               If $sIgnore AND  StringRegExp($szBuffer, "(?i)" & $sIgnore) Then
                  $szBuffer = FileFindNextFile ($Hfile)
                  ContinueLoop
               EndIf
               If StringInStr($szRoot & $szBuffer, $sChk) Then $szPathlist &= $szRoot & $szBuffer & "\*"
            EndIf
            $szBuffer = FileFindNextFile ($Hfile)
         Wend
         FileClose ($Hfile)
      EndIf
      $szReturn = $szPathList

   If $iRecurs = 1 Then
      $szPathList = StringTrimLeft($szPathlist, 1)
      $szRoot = StringLeft($szPathList, StringInStr($szPathlist, '*') -1)
      While 1
         $hFile = FileFindFirstFile ($szRoot & '*')
         If $hFile >= 0 Then
            $szBuffer = FileFindNextFile ($Hfile)
         While NOT @Error
            If StringInStr(FileGetAttrib($szRoot & $szBuffer), 'D') Then
               If NOT $sIgnore Then
                  If StringInStr($szRoot & $szBuffer, $sChk) Then $szPathlist &= $szRoot & $szBuffer & "\*"
                  If StringInStr($szRoot & $szBuffer, $sChk) Then $szReturn &= $szRoot & $szBuffer & "\*"
               Else
                  If NOT StringRegExp($szBuffer, "(?i)" & $sIgnore) Then
                     If StringInStr($szRoot & $szBuffer, $sChk) Then $szPathlist &= $szRoot & $szBuffer & "\*"
                     If StringInStr($szRoot & $szBuffer, $sChk) Then $szReturn &= $szRoot & $szBuffer & "\*"
                  EndIf
               EndIf
            EndIf
            $szBuffer = FileFindNextFile ($Hfile)
         Wend
         FileClose($hFile)
         $szPathList = StringReplace($szPathList, $szRoot, '')
         EndIf
         If $szPathList == '*' Then ExitLoop
         $szPathlist = StringTrimLeft ($szPathlist, 1)
         $szRoot = StringLeft ($szPathlist, StringInStr ($szPathlist, "*") - 1) & "\"
         $szPathlist = StringTrimLeft ($szPathlist, StringInStr ($szPathlist, "*") - 1)
      Wend
   EndIf
   If StringLeft($szReturn, 1) = '*' Then $szReturn = StringTrimLeft($szReturn, 1)
   $szReturn = StringReplace($szReturn, '\\', '\')
   If StringRight($szReturn, 1) = '*' Then $szReturn = StringTrimRight($szReturn,1)
   If NOT $iNoRoot Then $szReturn = $oRoot & $szReturn
   $szReturn = StringSplit($szReturn,'*')
   If $szReturn = '*' or $szReturn = '' Then Return 0
   ; _ArraySort($szReturn) ;; << uncomment and #include <array.au3> to return a sorted array
   Return $szReturn
EndFunc   ;<==> _FldrListToArray()

;;  Private Functions

Func _FldrDate($Dt, $Ext_Date, $Mth_AsText, $T_Txt)
   Local $Tday = 0
   If $Ext_Date = 0 Then Return $Dt
   Local $Disp_Mon = StringSplit('January|February|March|April|May|June|July|August|September|October|November|December', '|')
   Local $y = StringLeft($Dt, 4)
   Local $m = StringMid($Dt,5,2)
   Local $d = StringMid($Dt, 7, 2)
   If $y = @Year AND $m = @Mon AND $d = @Mday Then $Tday = 1
   Local $t = StringMid($Dt, 9)
   $t = StringLeft($t,2) & ':' & StringMid($t, 3,2) & ':' & StringRight($t, 2)
   If StringLeft( $t, 2) < 12 Then
      $t &= ' am'
   Else
      $t = StringLeft($t, 2) - 12 & StringMid($t, 3)
      $t &= ' pm'
   EndIf
   If $Tday = 1 AND $Mth_AsText = 1 AND $T_Txt = 1 Then Return 'Today at ' & $t
   If $Mth_AsText = 1 Then $m = $Disp_Mon[$m]
   Return $m & ' ' & $d & ' ' & $y & ' at ' & $t
EndFunc    ;<===> _FldrDate()