Board logo

标题: [转载代码] PowerShell删除指定天数之前的文件 [打印本页]

作者: DAIC    时间: 2013-11-8 13:43     标题: PowerShell删除指定天数之前的文件

Script to delete files older than x-days. The script is built to be used as a scheduled task, it automatically generates a logfile name based on the copy location and the current date/time. There are various levels of logging available and the script can also run in -listonly mode in which it only lists the files it would otherwise delete. There are two main routines, one to delete the files and a second routine that checks if there are any empty folders left that could be deleted.

There are two logging levels available, failed only and verbose, which logs every file and folder that is deleted.

http://gallery.technet.microsoft.com/scriptcenter/Delete-files-older-than-x-13b29c09
  1. <#   
  2. .SYNOPSIS   
  3. Script to delete or list old files in a folder
  4.    
  5. .DESCRIPTION
  6. Script to delete files older than x-days. The script is built to be used as a scheduled task, it automatically generates a logfile name based on the copy location and the current date/time. There are various levels of logging available and the script can also run in -listonly mode in which it only lists the files it would otherwise delete. There are two main routines, one to delete the files and a second routine that checks if there are any empty folders left that could be deleted.
  7. .PARAMETER FolderPath
  8. The path that will be recusively scanned for old files.
  9. .PARAMETER Fileage
  10. Filter for age of file, entered in days. Use -1 for all files to be removed.
  11. .PARAMETER LogFile
  12. Specifies the full path and filename of the logfile. When the LogFile parameter is used in combination with -autolog only the path is required.
  13. .PARAMETER AutoLog
  14. Automatically generates filename at path specified in -logfile. If a filename is specified in the LogFile parameter and the AutoLog parameter is used only the path specified in LogFile is used. The file name is created with the following naming convention:
  15. "Autolog_<FolderPath><dd-MM-yyyy_HHmm.ss>.log"
  16. .PARAMETER ExcludePath
  17. Specifies a path or multiple paths in quotes separated by commas. The Exclude parameter only accepts full paths, relative paths should not be used.
  18. .PARAMETER IncludePath
  19. Specifies a path or multiple paths in quotes separated by commas. The Exclude parameter only accepts full paths, relative paths should not be used. IncludePath is processed before ExcludePath.
  20. .PARAMETER RegExPath
  21. This switch affects both the IncludePath and ExcludePath parameters. Instead of matching against a path name a regular expression is used. For more information about regular expressions see the help file: Get-Help about_Regular_Expressions. The regular expression is only matched against the path of a file, so no file names can be excluded by utilizing ExcludePath.
  22. .PARAMETER ExcludeFileExtension
  23. Specifies an extension or multiple extensions in quotes, separated by commas. The extensions will be excluded from deletion. Asterisk can be used as a wildcard.
  24. .PARAMETER IncludeFileExtension
  25. Specifies an extension or multiple extensions in quotes, separated by commas. The extensions will be included in the deletion, all other extensions will implicitly be excluded. Asterisk can be used as a wildcard.
  26. .PARAMETER EmailTo
  27. Should be used in conjunction with the EmailFrom and EmailSmtpServer parameters, this parameter can take an email address or an array of email address to whom the logfile will be emailed.
  28. .PARAMETER EmailFrom
  29. Should be used in conjunction with the EmailTo and EmailSmtpServer parameters, this parameter can take an email address which is set as the email address in the from field.
  30. .PARAMETER EmailSmtpServer
  31. Should be used in conjunction with the EmailTo and EmailFrom parameters, this parameter takes the fully qualified domain name of your smtp server.
  32. .PARAMETER EmailSubject
  33. Option email parameter, allows for setting a different subject for the email containing the log file. The default formatting of the subject is 'deleteold.ps1 started at: $StartTime FolderPath: $FolderPath'
  34. .PARAMETER ExcludeDate
  35. If the ExcludeDate parameter is specified the query is converted by the ConvertFrom-Query function. The output of that table is a hashtable that is splatted to the ConvertTo-DateObject function which returns an array of dates. All files that match a date in the returned array will be excluded from deletion.
  36. Query examples:
  37. Week:
  38. 'Week,sat,-1'
  39. Will list all saturday until the LimitYear maximum is reached
  40. 'Week,wed,5'
  41. Will list the last 5 wednesdays
  42. Month:
  43. 'Month,first,4'
  44. Will list the first day of the last four months
  45. 'Month,last,-1'
  46. Will list the last day of until the LimitYear maximum is reached. If the current date is the last day of the month the current day is also listed.
  47. 'Month,30,3'
  48. Will list the 30th of the last three months, if february is in the results it will be ignored because it does not have 30 days.
  49. 'Month,31,-1'
  50. Will only list the 31st of the month, all months that have less than 31 days are excluded. Will list untli the LimitYear maximum has been reached.
  51. 'Month,15,4','Month,last,-1'
  52. Will list the first day of the last four months and list the last day of until the LimitYear maximum is reached. If the current date is the last day of the month the current day is also listed.
  53. Quarter:
  54. 'Quarter,first,-1'
  55. Will list the first day of a quarter until the LimitYear maximum is reached
  56. 'Quarter,last,6'
  57. Will list the last day of the past six quarters. If the current date is the last day of the quarter the current day is also listed.
  58. 'Quarter,91,5'
  59. Will only list the 91st day of each quarter, in non-leap years this will be the last three quarters. In leap years the first quarter also has 91 days and will therefore be included in the results
  60. 'Quarter,92,-1'
  61. Will only list the 92nd day of each quarter, so only display the 30th of september and 31st of december. The first two quarters of a year have less days and will not be listed. Will run until limityear maximum is reached
  62. Year:
  63. 'Year,last,4'
  64. Will list the 31st of december for the last 4 years
  65. 'Year,first,-1'
  66. Will list the 1st of january until the Limityear maximum has been reached
  67. 'Year,15,-1'
  68. Will list the 15 of january until the LimitYear maximum has been reached
  69. 'Year,366,5'
  70. Will list only the 366st day, only the last day of the last 5 leap years
  71. Specific Date:
  72. 'Date,2010-05-15'
  73. Will list 15th of may 2010
  74. 'Date,2012/12/12'
  75. Will list 12th of december 2012
  76. Date Ranges:
  77. 'DateRange,2010-05-05,10'
  78. Will list 10 dates, starting at the 5th of May 2010 continuing up until the 14th of May 2010
  79. 'LimitYear,2008'
  80. Will place the limit of LimitYear to 2008, the default value of this parameter is 2010.
  81. Any combination or queries is allowed by comma-separating the queries for example. Query elements Week/Month/Quarter/Year can not be used twice when combining queries. The Date value can be used multiple times:
  82. 'Week,Fri,10','Year,last,-1','LimitYear,1950'
  83. Will list the last 10 fridays and the 31st of december for all years until the LimitYear is reached
  84. 'Week,Thu,4','Month,last,-1','Quarter,first,6','Year,last,10','LimitYear,2012','Date,1990-12-31','Date,1995-5-31'
  85. Will list the last four Thursdays, the last day of the month until LimitYear maximum has been reached, the first day of the first 6 quarters and the 31st of december for the last 10 years and the two specific dates 1990-12-31 & 1995-5-31.
  86. .PARAMETER ListOnly
  87. Only lists, does not remove or modify files. This parameter can be used to establish which files would be deleted if the script is executed.
  88. .PARAMETER VerboseLog
  89. Logs all delete operations to log, default behaviour of the script is to log failed only.
  90. .PARAMETER AppendLog
  91. Appends to existing logfile, default behaviour of the script is to replace existing log files if the log file already exists. If log file does not exist log file will be created as it normally would.
  92. .PARAMETER CreateTime
  93. Deletes files based on CreationTime, the default behaviour of the script is to delete based on LastWriteTime.
  94. .PARAMETER LastAccessTime
  95. Deletes files based on LastAccessTime, the default behaviour of the script is to delete based on LastWriteTime.
  96. .PARAMETER CleanFolders
  97. If this switch is specified any empty folder will be removed. Default behaviour of this script is to only delete folders that contained old files.
  98. .PARAMETER NoFolder
  99. If this switch is specified only files will be deleted and the existing folder will be retained.
  100. .NOTES   
  101. Name: deleteold.ps1
  102. Author: Jaap Brasser
  103. Version: 1.9.2
  104. DateUpdated: 2013-09-26
  105. .LINK
  106. http://www.jaapbrasser.com
  107. .EXAMPLE   
  108. .\deleteold.ps1 -FolderPath H:\scripts -FileAge 100 -ListOnly -LogFile H:\log.log
  109. Description:
  110. Searches through the H:\scripts folder and writes a logfile containing files that were last modified 100 days ago and older.
  111. .EXAMPLE
  112. .\deleteold.ps1 -FolderPath H:\scripts -FileAge 30 -LogFile H:\log.log -VerboseLog
  113. Description:
  114. Searches through the H:\scripts folder and deletes files that were modified 30 days ago or before, writes all operations, success and failed, to a logfile on the H: drive.
  115. .EXAMPLE
  116. .\deleteold.ps1 -FolderPath C:\docs -FileAge 30 -LogFile H:\log.log -ExcludePath "C:\docs\finance\","C:\docs\hr\"
  117. Description:
  118. Searches through the C:\docs folder and deletes files, exluding the finance and hr folders in C:\docs.
  119. .EXAMPLE
  120. .\deleteold.ps1 -FolderPath C:\Folder -FileAge 30 -LogFile H:\log.log -IncludePath "C:\Folder\Docs\","C:\Folder\Users\" -ExcludePath "C:\docs\finance\","C:\docs\hr\"
  121. Description:
  122. Only check files in the C:\Folder\Docs\ and C:\Folder\Users\ Folders not any other folders in C:\Folders and explicitly exclude the Finance an HR folders in C:\Folder\Docs.
  123. .EXAMPLE
  124. .\deleteold.ps1 -FolderPath C:\Folder -FileAge 30 -LogFile H:\log.log -IncludePath "C:\Folder\Docs\","C:\Folder\Users\" -ExcludePath "C:\docs\finance\","C:\docs\hr\" -ExcludeDate 'Week,Fri,10','Year,last,-1','LimitYear,1950'
  125. Description:
  126. Only check files in the C:\Folder\Docs\ and C:\Folder\Users\ Folders not any other folders in C:\Folders and explicitly exclude the Finance an HR folders in C:\Folder\Docs. Also excludes files based on Date, excluding the last 10 fridays and the 31st of December for all years back until 1950
  127. .EXAMPLE
  128. .\deleteold.ps1 -FolderPath C:\Folder -FileAge 60 -LogFile H:\log.log -IncludePath .*images.* -RegExPath
  129. Description:
  130. Delete files older than 60 days and only delete files that contain 'images' in their path name.
  131. .EXAMPLE
  132. .\deleteold.ps1 -FolderPath C:\Folder -FileAge 45 -LastAccessTime -LogFile H:\log.log
  133. Description:
  134. Delete files that have not been access for more than 45 days.
  135. .EXAMPLE
  136. PowerShell.exe deleteold.ps1 -FolderPath 'H:\admin_jaap' -FileAge 10 -LogFile C:\log -AutoLog
  137. Description:
  138. Launches the script from batchfile or command prompt a filename is automatically generated since the -AutoLog parameter is used. Note the quotes '' that are used for the FolderPath parameter.
  139. .EXAMPLE
  140. .\deleteold.ps1 -FolderPath C:\docs -FileAge 30 -logfile h:\log.log -CreateTime -NoFolder
  141. Description:
  142. Deletes all files that were created 30 days ago or before in the C:\docs folder. No folders are deleted.
  143. .EXAMPLE
  144. .\deleteold.ps1 -FolderPath C:\docs -FileAge 30 -logfile h:\log.log -CreateTime -CleanFolders
  145. Description:
  146. Deletes all files that were created 30 days ago or before in the C:\docs folder. Only folders that contained old files and are empty after the deletion of those files will be deleted.
  147. .EXAMPLE
  148. .\deleteold.ps1 -folderpath c:\users\jaapbrasser\desktop -fileage 10 -log c:\log.txt -autolog -verboselog -IncludeFileExtension '.xls*','.doc*'
  149. Description:
  150. Deletes files older than 10 days, only deletes files matching the .xls* and .doc* patterns eg: .doc and .docx files. Log file is stored in the root of the C-drive with an automatically generated name.
  151. .EXAMPLE
  152. .\deleteold.ps1 -folderpath c:\users\jaapbrasser\desktop -fileage 10 -log c:\log.txt -autolog -verboselog -ExcludeFileExtension .xls
  153. Description:
  154. Deletes files older than 10 days, excluding xls files. Log file is stored in the root of the C-drive with an automatically generated name.
  155. .EXAMPLE
  156. .\deleteold.ps1 -FolderPath C:\docs -FileAge 30 -LogFile h:\log.log -ExcludeDate 'Week,Thu,4','Month,last,-1','Quarter,first,6','Year,last,10','LimitYear,2012','Date,1990-12-31','Date,1995-5-31'
  157. Description:
  158. Deletes all files that were created 30 days ago or before in the C:\docs folder. With the exclusion of files last modified/created specified in the -ExcludeDate query.
  159. .EXAMPLE   
  160. .\deleteold.ps1 -FolderPath H:\scripts -FileAge 100 -ListOnly -LogFile H:\log.log -ExcludeDate 'DateRange,2005-05-16,8'
  161. Description:
  162. Searches through the H:\scripts folder and writes a logfile containing files that were last modified 100 days ago and older. Excluding files modified on the 16th of May 2005 and the following seven days.
  163. .EXAMPLE
  164. .\deleteold.ps1 -FolderPath C:\docs -ListOnly -FileAge 30 -LogFile h:\log.log -ExcludeDate 'Month,15,5','Month,16,5' -EmailTo jaapbrasser@corp.co -EmailFrom jaapbrasser@corp.co -EmailSmtpServer smtp.corp.co
  165. Description:
  166. Deletes all files that were created 30 days ago or before in the C:\docs folder. With the exclusion of files last modified/created on either the 15th or 16th of the last five months. After completion of the script the log file will be emailed to jaapbrasser@corp.co via the smtp.corp.co smtp server.
  167. #>
  168. #region Parameters
  169. param(
  170.     [string]$FolderPath,
  171. [string]$FileAge,
  172. [string]$LogFile,
  173.     [string[]]$ExcludePath,
  174.     [string[]]$IncludePath,
  175. [string[]]$ExcludeFileExtension,
  176.     [string[]]$IncludeFileExtension,
  177.     [string[]]$ExcludeDate,
  178.     [string[]]$EmailTo,
  179.     [string]$EmailFrom,
  180.     [string]$EmailSmtpServer,
  181.     [string]$EmailSubject,
  182.     [switch]$ListOnly,
  183. [switch]$VerboseLog,
  184. [switch]$AutoLog,
  185.     [switch]$AppendLog,
  186. [switch]$CreateTime,
  187.     [switch]$LastAccessTime,
  188.     [switch]$CleanFolders,
  189.     [switch]$NoFolder,
  190.     [switch]$RegExPath
  191. )
  192. #endregion
  193. #region Functions
  194. # Function to convert the query provided in -ExcludeDate to a format that can be parsed by the ConvertTo-DateObject function
  195. function ConvertFrom-DateQuery {
  196. param (
  197.     $Query
  198. )
  199.     try {
  200.         $CsvQuery = Convertfrom-Csv -InputObject $Query -Delimiter ',' -Header "Type","Day","Repeat"
  201.         $ConvertCsvSuccess = $true
  202.     } catch {
  203.         Write-Warning "Query is in incorrect format, please supply query in proper format"
  204.         $ConvertCsvSuccess = $false
  205.     }
  206.     if ($ConvertCsvSuccess) {
  207.         $Check=$HashOutput = @{}
  208.         foreach ($Entry in $CsvQuery) {
  209.             switch ($Entry.Type) {
  210.                 'week' {
  211.                     # Convert named dates to correct format
  212.                     switch ($Entry.Day)
  213.                     {
  214.                         # DayOfWeek starts count at 0, referring to the [datetime] property DayOfWeek
  215.                         'sun' {
  216.                             $HashOutput.DayOfWeek = 0
  217.                             $HashOutput.WeekRepeat = $Entry.Repeat
  218.                         }
  219.                         'mon' {
  220.                             $HashOutput.DayOfWeek = 1
  221.                             $HashOutput.WeekRepeat = $Entry.Repeat
  222.                         }
  223.                         'tue' {
  224.                             $HashOutput.DayOfWeek = 2
  225.                             $HashOutput.WeekRepeat = $Entry.Repeat
  226.                         }
  227.                         'wed' {
  228.                             $HashOutput.DayOfWeek = 3
  229.                             $HashOutput.WeekRepeat = $Entry.Repeat
  230.                         }
  231.                         'thu' {
  232.                             $HashOutput.DayOfWeek = 4
  233.                             $HashOutput.WeekRepeat = $Entry.Repeat
  234.                         }
  235.                         'fri' {
  236.                             $HashOutput.DayOfWeek = 5
  237.                             $HashOutput.WeekRepeat = $Entry.Repeat
  238.                         }
  239.                         'sat' {
  240.                             $HashOutput.DayOfWeek = 6
  241.                             $HashOutput.WeekRepeat = $Entry.Repeat
  242.                         }
  243.                         Default {$Check.WeekSuccess = $false}
  244.                     }
  245.                 }
  246.                 'month' {
  247.                     # Convert named dates to correct format
  248.                     switch ($Entry.Day)
  249.                     {
  250.                         # DayOfMonth starts count at 0, referring to the last day of the month with zero
  251.                         'first' {
  252.                             [array]$HashOutput.DayOfMonth += 1
  253.                             [array]$HashOutput.MonthRepeat += $Entry.Repeat
  254.                         }
  255.                         'last' {
  256.                             [array]$HashOutput.DayOfMonth += 0
  257.                             [array]$HashOutput.MonthRepeat += $Entry.Repeat
  258.                         }
  259.                         {(1..31) -contains $_} {
  260.                             [array]$HashOutput.DayOfMonth += $Entry.Day
  261.                             [array]$HashOutput.MonthRepeat += $Entry.Repeat
  262.                         }
  263.                         Default {$Check.MonthSuccess = $false}
  264.                     }
  265.                 }
  266.                 'quarter' {
  267.                     # Count the number of times the quarter argument is used, used in final check of values
  268.                     $QuarterCount++
  269.                     # Convert named dates to correct format
  270.                     switch ($Entry.Day)
  271.                     {
  272.                         # DayOfMonth starts count at 0, referring to the last day of the month with zero
  273.                         'first' {
  274.                             $HashOutput.DayOfQuarter = 1
  275.                             $HashOutput.QuarterRepeat = $Entry.Repeat
  276.                         }
  277.                         'last' {
  278.                             $HashOutput.DayOfQuarter = 0
  279.                             $HashOutput.QuarterRepeat = $Entry.Repeat
  280.                         }
  281.                         {(1..92) -contains $_} {
  282.                             $HashOutput.DayOfQuarter = $Entry.Day
  283.                             $HashOutput.QuarterRepeat = $Entry.Repeat
  284.                         }
  285.                         Default {$Check.QuarterSuccess = $false}
  286.                     }
  287.                 }
  288.                 'year' {
  289.                     # Convert named dates to correct format
  290.                     switch ($Entry.Day)
  291.                     {
  292.                         # DayOfMonth starts count at 0, referring to the last day of the month with zero
  293.                         'first' {
  294.                             $HashOutput.DayOfYear = 1
  295.                             $HashOutput.DayOfYearRepeat = $Entry.Repeat
  296.                         }
  297.                         'last' {
  298.                             $HashOutput.DayOfYear = 0
  299.                             $HashOutput.DayOfYearRepeat = $Entry.Repeat
  300.                         }
  301.                         {(1..366) -contains $_} {
  302.                             $HashOutput.DayOfYear = $Entry.Day
  303.                             $HashOutput.DayOfYearRepeat = $Entry.Repeat
  304.                         }
  305.                         Default {$Check.YearSuccess = $false}
  306.                     }
  307.                 }
  308.                 'date' {
  309.                     # Verify if the date is in the correct format
  310.                     switch ($Entry.Day)
  311.                     {
  312.                         {try {[DateTime]"$($Entry.Day)"} catch{}} {
  313.                             [array]$HashOutput.DateDay += $Entry.Day
  314.                         }
  315.                         Default {$Check.DateSuccess = $false}
  316.                     }
  317.                 }
  318.                 'daterange' {
  319.                     # Verify if the date is in the correct format
  320.                     switch ($Entry.Day)
  321.                     {
  322.                         {try {[DateTime]"$($Entry.Day)"} catch{}} {
  323.                             $HashOutput.DateRange += $Entry.Day
  324.                             $HashOutput.DateRangeRepeat += $Entry.Repeat
  325.                         }
  326.                         Default {$Check.DateRangeSuccess = $false}
  327.                     }
  328.                 }
  329.                 'limityear' {
  330.                     switch ($Entry.Day)
  331.                     {
  332.                         {(1000..2100) -contains $_} {
  333.                             $HashOutput.LimitYear = $Entry.Day
  334.                         }
  335.                         Default {$Check.LimitYearSuccess = $false}
  336.                     }
  337.                 }
  338.                 Default {
  339.                     $QueryContentCorrect = $false
  340.                 }
  341.             }
  342.         }
  343.         $HashOutput
  344.     }
  345. }
  346. # Function that outputs an array of date objects that can be used to exclude certain files from deletion
  347. function ConvertTo-DateObject {
  348. param(
  349.     [validaterange(0,6)]
  350.     $DayOfWeek,
  351.     [int]$WeekRepeat=1,
  352.     [validaterange(0,31)]
  353.     $DayOfMonth,
  354.     $MonthRepeat=1,
  355.     [validaterange(0,92)]
  356.     $DayOfQuarter,
  357.     [int]$QuarterRepeat=1,
  358.     [validaterange(0,366)]
  359.     $DayOfYear,
  360.     [int]$DayOfYearRepeat=1,
  361.     $DateDay,
  362.     $DateRange,
  363.     [int]$DateRangeRepeat=1,
  364.     [validaterange(1000,2100)]
  365.     [int]$LimitYear = 2010
  366. )
  367.     # Define variable
  368.     $CurrentDate = Get-Date
  369.     if ($DayOfWeek -ne $null) {
  370.         $CurrentWeekDayInt = $CurrentDate.DayOfWeek.value__
  371.             # Loop runs for number of times specified in the WeekRepeat parameter
  372.             for ($j = 0; $j -lt $WeekRepeat; $j++)
  373.                 {
  374.                     $CheckDate = $CurrentDate.Date.AddDays(-((7*$j)+$CurrentWeekDayInt-$DayOfWeek))
  375.                     # Only display date if date is larger than current date, this is to exclude dates in the current week
  376.                     if ($CheckDate -le $CurrentDate) {
  377.                         $CheckDate
  378.                     } else {
  379.                         # Increase weekrepeat, to ensure the correct amount of repeats are executed when date returned is
  380.                         # higher than current date
  381.                         $WeekRepeat++
  382.                     }
  383.                 }
  384.             
  385.             # Loop runs until $LimitYear parameter is exceeded
  386. if ($WeekRepeat -eq -1) {
  387.                 $j=0
  388.                 do {
  389.                     $CheckDate = $CurrentDate.AddDays(-((7*$j)+$CurrentWeekDayInt-$DayOfWeek))
  390.                     $j++
  391.                     # Only display date if date is larger than current date, this is to exclude dates in the current week
  392.                     if ($CheckDate -le $CurrentDate) {
  393.                         $CheckDate
  394.                     }
  395.                 } while ($LimitYear -le $CheckDate.Adddays(-7).Year)
  396.             }
  397.         }
  398.     if ($DayOfMonth -ne $null) {
  399.         for ($MonthCnt = 0; $MonthCnt -lt $DayOfMonth.Count; $MonthCnt++) {
  400.             # Loop runs for number of times specified in the MonthRepeat parameter
  401.             for ($j = 0; $j -lt $MonthRepeat[$MonthCnt]; $j++)
  402.                 {
  403.                     $CheckDate = $CurrentDate.Date.AddMonths(-$j).AddDays($DayOfMonth[$MonthCnt]-$CurrentDate.Day)
  404.                     # Only display date if date is larger than current date, this is to exclude dates ahead of the current date and
  405.                     # to list only output the possible dates. If a value of 29 or higher is specified as a DayOfMonth value
  406.                     # only possible dates are listed.
  407.                     if ($CheckDate -le $CurrentDate -and $(if ($DayOfMonth[$MonthCnt] -ne 0) {$CheckDate.Day -eq $DayOfMonth[$MonthCnt]} else {$true})) {
  408.                         $CheckDate
  409.                     } else {
  410.                         # Increase MonthRepeat integer, to ensure the correct amount of repeats are executed when date returned is
  411.                         # higher than current date
  412.                         $MonthRepeat[$MonthCnt]++
  413.                     }
  414.                 }
  415.             
  416.             # Loop runs until $LimitYear parameter is exceeded
  417.     if ($MonthRepeat[$MonthCnt] -eq -1) {
  418.                 $j=0
  419.                 do {
  420.                     $CheckDate = $CurrentDate.Date.AddMonths(-$j).AddDays($DayOfMonth[$MonthCnt]-$CurrentDate.Day)
  421.                     $j++
  422.                     # Only display date if date is larger than current date, this is to exclude dates ahead of the current date and
  423.                     # to list only output the possible dates. For example if a value of 29 or higher is specified as a DayOfMonth value
  424.                     # only possible dates are listed.
  425.                     if ($CheckDate -le $CurrentDate -and $(if ($DayOfMonth[$MonthCnt] -ne 0) {$CheckDate.Day -eq $DayOfMonth[$MonthCnt]} else {$true})) {
  426.                         $CheckDate
  427.                     }
  428.                 } while ($LimitYear -le $CheckDate.Adddays(-31).Year)
  429.             }
  430.         }
  431.     }
  432.     if ($DayOfQuarter -ne $null) {
  433.         # Set quarter int to current quarter value $QuarterInt
  434.         $QuarterInt = [int](($CurrentDate.Month+1)/3)
  435.         $QuarterYearInt = $CurrentDate.Year
  436.         $QuarterLoopCount = $QuarterRepeat
  437.         $j = 0
  438.         
  439.         do {
  440.             switch ($QuarterInt) {
  441.                 1 {
  442.                     $CheckDate = ([DateTime]::ParseExact("$($QuarterYearInt)0101",'yyyyMMdd',$null)).AddDays($DayOfQuarter-1)
  443.                     
  444.                     # Check for number of days in the 1st quarter, this depends on leap years
  445.                     $DaysInFeb = ([DateTime]::ParseExact("$($QuarterYearInt)0301",'yyyyMMdd',$null)).AddDays(-1).Day
  446.                     $DaysInCurrentQuarter = 31+$DaysInFeb+31
  447.                         
  448.                     # If the number of days is larger that the total number of days in this quarter the quarter will be excluded
  449.                     if ($DayOfQuarter -gt $DaysInCurrentQuarter) {
  450.                         $CheckDate = $null
  451.                     }
  452.                     # This check is built-in to return the date last date of the current quarter, to ensure consistent results
  453.                     # in case the command is executed on the last day of a quarter
  454.                     if ($DayOfQuarter -eq 0) {
  455.                         $CheckDate = [DateTime]::ParseExact("$($QuarterYearInt)0331",'yyyyMMdd',$null)
  456.                     }
  457.                     $QuarterInt = 4
  458.                     $QuarterYearInt--
  459.                 }
  460.                 2 {
  461.                     $CheckDate = ([DateTime]::ParseExact("$($QuarterYearInt)0401",'yyyyMMdd',$null)).AddDays($DayOfQuarter-1)
  462.                         
  463.                     # Check for number of days in the 2nd quarter
  464.                     $DaysInCurrentQuarter = 30+31+30
  465.                         
  466.                     # If the number of days is larger that the total number of days in this quarter the quarter will be excluded
  467.                     if ($DayOfQuarter -gt $DaysInCurrentQuarter) {
  468.                         $CheckDate = $null
  469.                     }
  470.                     # This check is built-in to return the date last date of the current quarter, to ensure consistent results
  471.                     # in case the command is executed on the last day of a quarter                       
  472.                     if ($DayOfQuarter -eq 0) {
  473.                         $CheckDate = [DateTime]::ParseExact("$($QuarterYearInt)0630",'yyyyMMdd',$null)
  474.                     }
  475.                         
  476.                     $QuarterInt = 1
  477.                 }
  478.                 3 {
  479.                     $CheckDate = ([DateTime]::ParseExact("$($QuarterYearInt)0701",'yyyyMMdd',$null)).AddDays($DayOfQuarter-1)
  480.                         
  481.                     # Check for number of days in the 3rd quarter
  482.                     $DaysInCurrentQuarter = 31+31+30
  483.                         
  484.                     # If the number of days is larger that the total number of days in this quarter the quarter will be excluded
  485.                     if ($DayOfQuarter -gt $DaysInCurrentQuarter) {
  486.                         $CheckDate = $null
  487.                     }
  488.                         
  489.                     # This check is built-in to return the date last date of the current quarter, to ensure consistent results
  490.                     # in case the command is executed on the last day of a quarter                       
  491.                     if ($DayOfQuarter -eq 0) {
  492.                         $CheckDate = [DateTime]::ParseExact("$($QuarterYearInt)0930",'yyyyMMdd',$null)
  493.                     }
  494.                     $QuarterInt = 2
  495.                 }
  496.                 4 {
  497.                     $CheckDate = ([DateTime]::ParseExact("$($QuarterYearInt)1001",'yyyyMMdd',$null)).AddDays($DayOfQuarter-1)
  498.                         
  499.                     # Check for number of days in the 4th quarter
  500.                     $DaysInCurrentQuarter = 31+30+31
  501.                         
  502.                     # If the number of days is larger that the total number of days in this quarter the quarter will be excluded
  503.                     if ($DayOfQuarter -gt $DaysInCurrentQuarter) {
  504.                         $CheckDate = $null
  505.                     }
  506.                     # This check is built-in to return the date last date of the current quarter, to ensure consistent results
  507.                     # in case the command is executed on the last day of a quarter                       
  508.                     if ($DayOfQuarter -eq 0) {
  509.                         $CheckDate = [DateTime]::ParseExact("$($QuarterYearInt)1231",'yyyyMMdd',$null)
  510.                     }                        
  511.                     $QuarterInt = 3
  512.                 }
  513.             }
  514.             # Only display date if date is larger than current date, and only execute check if $CheckDate is not equal to $null
  515.             if ($CheckDate -le $CurrentDate -and $CheckDate -ne $null) {
  516.                     
  517.                 # Only display the date if it is not further in the past than the limit year
  518.                 if ($CheckDate.Year -ge $LimitYear -and $QuarterRepeat -eq -1) {
  519.                     $CheckDate
  520.                 }
  521.                 # If the repeat parameter is not set to -1 display results regardless of limit year                    
  522.                 if ($QuarterRepeat -ne -1) {
  523.                     $CheckDate
  524.                     $j++
  525.                 } else {
  526.                     $QuarterLoopCount++
  527.                 }
  528.             }
  529.             # Added if statement to catch errors regarding
  530.         } while ($(if ($QuarterRepeat -eq -1) {$LimitYear -le $(if ($CheckDate) {$CheckDate.Year} else {9999})}
  531.                 else {$j -lt $QuarterLoopCount}))
  532.     }
  533.     if ($DayOfYear -ne $null) {
  534.         $YearLoopCount = $DayOfYearRepeat
  535.         $YearInt = $CurrentDate.Year
  536.         $j = 0
  537.         # Mainloop containing the loop for selecting a day of a year
  538.         do {
  539.             $CheckDate = ([DateTime]::ParseExact("$($YearInt)0101",'yyyyMMdd',$null)).AddDays($DayOfYear-1)
  540.             
  541.             # If the last day of the year is specified, a year is added to get consistent results when the query is executed on last day of the year
  542.             if ($DayOfYear -eq 0) {
  543.                 $CheckDate = $CheckDate.AddYears(1)
  544.             }
  545.             
  546.             # Set checkdate to null to allow for selection of last day of leap year
  547.             if (($DayOfYear -eq 366) -and !([DateTime]::IsLeapYear($YearInt))) {
  548.                 $CheckDate = $null
  549.             }
  550.             # Only display date if date is larger than current date, and only execute check if $CheckDate is not equal to $null
  551.             if ($CheckDate -le $CurrentDate -and $CheckDate -ne $null) {
  552.                 # Only display the date if it is not further in the past than the limit year
  553.                 if ($CheckDate.Year -ge $LimitYear -and $DayOfYearRepeat -eq -1) {
  554.                     $CheckDate
  555.                 }
  556.                 # If the repeat parameter is not set to -1 display results regardless of limit year
  557.                 if ($DayOfYearRepeat -ne -1) {
  558.                     $CheckDate
  559.                     $j++
  560.                 } else {
  561.                     $YearLoopCount++
  562.                 }
  563.             }
  564.             $YearInt--
  565.         } while ($(if ($DayOfYearRepeat -eq -1) {$LimitYear -le $(if ($CheckDate) {$CheckDate.Year} else {9999})}
  566.                 else {$j -lt $YearLoopCount}))
  567.     }
  568.     if ($DateDay -ne $null) {
  569.         foreach ($Date in $DateDay) {
  570.             try {
  571.                 $CheckDate = [DateTime]::ParseExact($Date,'yyyy-MM-dd',$null)
  572.             } catch {
  573.                 try {
  574.                     $CheckDate = [DateTime]::ParseExact($Date,'yyyy\/MM\/dd',$null)
  575.                 } catch {}
  576.             }
  577.             
  578.             if ($CheckDate -le $CurrentDate) {
  579.                 $CheckDate
  580.             }
  581.             $CheckDate=$null
  582.         }
  583.     }
  584.     if ($DateRange -ne $null) {
  585.         $CheckDate=$null
  586.         try {
  587.             $CheckDate = [DateTime]::ParseExact($DateRange,'yyyy-MM-dd',$null)
  588.         } catch {
  589.             try {
  590.                 $CheckDate = [DateTime]::ParseExact($DateRange,'yyyy\/MM\/dd',$null)
  591.             } catch {}
  592.         }
  593.         if ($CheckDate) {
  594.             for ($k = 0; $k -lt $DateRangeRepeat; $k++) {
  595.                 if ($CheckDate -le $CurrentDate) {
  596.                     $CheckDate
  597.                 }
  598.                 $CheckDate = $CheckDate.AddDays(1)
  599.             }
  600.         }
  601.     }
  602. }
  603. # Function that is triggered when the -autolog switch is active
  604. function F_Autolog {
  605. # Gets date and reformats to be used in log filename
  606. $TempDate = (get-date).ToString("dd-MM-yyyy_HHmm.ss")
  607. # Reformats $FolderPath so it can be used in the log filename
  608. $TempFolderPath = $FolderPath -replace '\\','_'
  609. $TempFolderPath = $TempFolderPath -replace ':',''
  610. $TempFolderPath = $TempFolderPath -replace ' ',''
  611. # Checks if the logfile is either pointing at a folder or a logfile and removes
  612. # Any trailing backslashes
  613. $TestLogPath = Test-Path $LogFile -PathType Container
  614. if (-not $TestLogPath) {
  615.         $LogFile = Split-Path $LogFile -Erroraction SilentlyContinue
  616.     }
  617. if ($LogFile.SubString($LogFile.Length-1,1) -eq "\") {
  618.         $LogFile = $LogFile.SubString(0,$LogFile.Length-1)
  619.     }
  620. # Combines the date and the path scanned into the log filename
  621. $script:LogFile = "$LogFile\Autolog_$TempFolderPath$TempDate.log"
  622. }
  623. # Function which contains the loop in which files are deleted. If a file fails to be deleted
  624. # an error is logged and the error message is written to the log.
  625. # $count is used to speed up the delete fileloop and will also be used for other large loops in the script
  626. function F_Deleteoldfiles {
  627. $Count = $FileList.Count
  628. for ($j=0;$j -lt $Count;$j++) {
  629. $TempFile = $FileList[$j].FullName
  630. $TempSize = $FileList[$j].Length
  631. if (-not $ListOnly) {Remove-Item -LiteralPath $Tempfile -Force -ErrorAction SilentlyContinue}
  632. if (-not $?) {
  633. $TempErrorVar = "$($Error[0].ToString()) ::: $($Error[0].targetobject)"
  634. "`tFAILED FILE`t`t$TempErrorVar" >> $LogFile
  635. $script:FilesFailed++
  636. $script:FailedSize+=$TempSize
  637. } else {
  638. if (-not $ListOnly) {
  639.                 $script:FilesNumber++;$script:FilesSize+=$TempSize
  640.                 if ($VerboseLog) {
  641.                     switch ($true) {
  642.                         {$CreateTime} {"`tDELETED FILE`t$($FileList[$j].CreationTime.ToString('yyyy-MM-dd hh:mm:ss'))`t$($FileList[$j].Length.ToString().PadLeft(15))`t$tempfile" >> $LogFile}
  643.                         {$LastAccessTime} {"`tDELETED FILE`t$($FileList[$j].LastAccessTime.ToString('yyyy-MM-dd hh:mm:ss'))`t$($FileList[$j].Length.ToString().PadLeft(15))`t$tempfile" >> $LogFile}
  644.                         Default {"`tDELETED FILE`t$($FileList[$j].LastWriteTime.ToString('yyyy-MM-dd hh:mm:ss'))`t$($FileList[$j].Length.ToString().PadLeft(15))`t$tempfile" >> $LogFile}
  645.                     }
  646.                 }
  647.             }
  648. }
  649. if($ListOnly) {
  650.             if ($VerboseLog) {
  651.                 switch ($true) {
  652.                     {$CreateTime} {"`tLISTONLY`t$($FileList[$j].CreationTime.ToString('yyyy-MM-dd hh:mm:ss'))`t$($FileList[$j].Length.ToString().PadLeft(15))`t$tempfile" >> $LogFile}
  653.                     {$LastAccessTime} {"`tLISTONLY`t$($FileList[$j].LastAccessTime.ToString('yyyy-MM-dd hh:mm:ss'))`t$($FileList[$j].Length.ToString().PadLeft(15))`t$tempfile" >> $LogFile}
  654.                     Default {"`tLISTONLY`t$($FileList[$j].LastWriteTime.ToString('yyyy-MM-dd hh:mm:ss'))`t$($FileList[$j].Length.ToString().PadLeft(15))`t$tempfile" >> $LogFile}
  655.                 }
  656.             } else {
  657.                 "`tLISTONLY`t$TempFile" >> $LogFile
  658.             }
  659. $script:FilesNumber++
  660. $script:FilesSize+=$TempSize
  661. }
  662. }
  663. }
  664. # Checks whether folder is empty and uses temporary variables
  665. # Main loop goes through list of folders, only deleting the empty folders
  666. # The if(-not $tempfolder) is the verification whether the folder is empty
  667. function F_Checkforemptyfolder {
  668. $FolderList = @($FolderList | sort-object @{Expression={$_.FullName.Length}; Ascending=$false})
  669. $Count = $FolderList.Count
  670. for ($j=0;$j -lt $Count;$j++) {
  671. $TempFolder = Get-ChildItem -LiteralPath $FolderList[$j].FullName -ErrorAction SilentlyContinue -Force
  672. if (-not $TempFolder) {
  673.     $TempName = $FolderList[$j].FullName
  674.     Remove-Item -LiteralPath $TempName -Force -Recurse -ErrorAction SilentlyContinue
  675. if(-not $?) {
  676. $TempErrorVar = "$($Error[0].ToString()) ::: $($Error[0].targetobject)"
  677. "`tFAILED FOLDER`t$TempErrorVar" >> $LogFile
  678. $script:FoldersFailed++
  679. } else {
  680. if ($VerboseLog) {
  681.                     switch ($true) {
  682.                         {$CreateTime} {"`tDELETED FOLDER`t$($FolderList[$j].CreationTime.ToString('yyyy-MM-dd hh:mm:ss'))`t`t`t$TempName" >> $LogFile}
  683.                         {$LastAccessTime} {"`tDELETED FOLDER`t$($FolderList[$j].LastAccessTime.ToString('yyyy-MM-dd hh:mm:ss'))`t`t`t$TempName" >> $LogFile}
  684.                         Default {"`tDELETED FOLDER`t$($FolderList[$j].LastWriteTime.ToString('yyyy-MM-dd hh:mm:ss'))`t`t`t$TempName" >> $LogFile}
  685.                     }
  686.                 }
  687. $script:FoldersNumber++
  688. }
  689. }
  690. }
  691. }
  692. #endregion
  693. # Check if correct parameters are used
  694. if (-not $FolderPath) {Write-Warning 'Please specify the -FolderPath variable, this parameter is required. Use Get-Help .\deleteold.ps1 to display help.';exit}
  695. if (-not $FileAge) {Write-Warning 'Please specify the -FileAge variable, this parameter is required. Use Get-Help .\deleteold.ps1 to display help.';exit}
  696. if (-not $LogFile) {Write-Warning 'Please specify the -LogFile variable, this parameter is required. Use Get-Help .\deleteold.ps1 to display help.';exit}
  697. if ($Autolog) {F_Autolog}
  698. # Sets up the variables
  699. $Startdate = Get-Date
  700. $LastWrite = $Startdate.AddDays(-$FileAge)
  701. $StartTime = $Startdate.ToShortDateString()+", "+$Startdate.ToLongTimeString()
  702. $Switches = "`r`n`t`t-FolderPath`r`n`t`t`t$FolderPath`r`n`t`t-FileAge $FileAge`r`n`t`t-LogFile`r`n`t`t`t$LogFile"
  703.     # Populate the switches string with the switches and parameters that are set
  704.     if ($IncludePath) {
  705.     $Switches += "`r`n`t`t-IncludePath"
  706.     for ($j=0;$j -lt $IncludePath.Count;$j++) {$Switches+= "`r`n`t`t`t";$Switches+= $IncludePath[$j]}
  707.     }
  708.     if ($ExcludePath) {
  709.     $Switches += "`r`n`t`t-ExcludePath"
  710.     for ($j=0;$j -lt $ExcludePath.Count;$j++) {$Switches+= "`r`n`t`t`t";$Switches+= $ExcludePath[$j]}
  711.     }
  712.     if ($IncludeFileExtension) {
  713.     $Switches += "`r`n`t`t-IncludeFileExtension"
  714.     for ($j=0;$j -lt $IncludeFileExtension.Count;$j++) {$Switches+= "`r`n`t`t`t";$Switches+= $IncludeFileExtension[$j]}
  715.     }
  716.     if ($ExcludeFileExtension) {
  717.     $Switches += "`r`n`t`t-ExcludeFileExtension"
  718.     for ($j=0;$j -lt $ExcludeFileExtension.Count;$j++) {$Switches+= "`r`n`t`t`t";$Switches+= $ExcludeFileExtension[$j]}
  719.     }
  720.     if ($ExcludeDate) {
  721.     $Switches+= "`r`n`t`t-ExcludeDate"
  722.         $ExcludeDate | ConvertFrom-Csv -Header:'Item1','Item2','Item3' -ErrorAction SilentlyContinue | ForEach-Object {
  723.             $Switches += "`r`n`t`t`t"
  724.             $Switches += ($_.Item1,$_.Item2,$_.Item3 -join ',').Trim(',')
  725.         }    
  726.     }
  727.     if ($EmailTo) {
  728.     $Switches += "`r`n`t`t-EmailTo"
  729.     for ($j=0;$j -lt $EmailTo.Count;$j++) {$Switches+= "`r`n`t`t`t";$Switches+= $EmailTo[$j]}
  730.     }
  731.     if ($EmailFrom) {
  732.         $Switches += "`r`n`t`t-EmailFrom`r`n`t`t`t$EmailFrom"
  733.     }
  734.     if ($EmailSubject) {
  735.         $Switches += "`r`n`t`t-EmailSubject`r`n`t`t`t$EmailSubject"
  736.     }
  737.     if ($EmailSmtpServer) {
  738.         $Switches += "`r`n`t`t-EmailSmtpServer`r`n`t`t`t$EmailSmtpServer"
  739.     }
  740.     if ($ListOnly) {$Switches+="`r`n`t`t-ListOnly"}
  741.     if ($VerboseLog) {$Switches+="`r`n`t`t-VerboseLog"}
  742.     if ($Autolog) {$Switches+="`r`n`t`t-AutoLog"}
  743.     if ($Appendlog) {$Switches+="`r`n`t`t-AppendLog"}
  744.     if ($CreateTime) {$Switches+="`r`n`t`t-CreateTime"}
  745.     if ($LastAccessTime) {$Switches+="`r`n`t`t-LastAccessTime"}
  746.     if ($CleanFolders) {$Switches+="`r`n`t`t-CleanFolders"}
  747.     if ($NoFolder) {$Switches+="`r`n`t`t-NoFolder"}
  748.     if ($RegExPath) {$Switches+="`r`n`t`t-RegExPath"}
  749. [long]$FilesSize = 0
  750. [long]$FailedSize = 0
  751. [int]$FilesNumber = 0
  752. [int]$FilesFailed = 0
  753. [int]$FoldersNumber = 0
  754. [int]$FoldersFailed = 0
  755. # Sets up the email splat, displays a warning if not all variables have been correctly entered
  756. if ($EmailTo -or $EmailFrom -or $EmailSmtpServer) {
  757.     if (($EmailTo,$EmailFrom,$EmailSmtpServer) -contains '') {
  758.         Write-Warning 'EmailTo EmailFrom and EmailSmtpServer parameters only work if all three parameters are used, no email sent...'
  759.     } else {
  760.         $EmailSplat = @{
  761.             To = $EmailTo
  762.             From = $EmailFrom
  763.             SmtpServer = $EmailSmtpServer
  764.             Attachments = $LogFile
  765.         }
  766.         if ($EmailSubject) {
  767.             $EmailSplat.Subject = $EmailSubject
  768.         } else {
  769.             $EmailSplat.Subject = "deleteold.ps1 started at: $StartTime FolderPath: $FolderPath"
  770.         }
  771.     }
  772. }
  773. # Output text to console and write log header
  774. Write-Output ("-"*79)
  775. Write-Output "  Deleteold`t::`tScript to delete old files from folders"
  776. Write-Output ("-"*79)
  777. Write-Output "`n   Started  :   $StartTime`n   Folder   :`t$FolderPath`n   Switches :`t$Switches`n"
  778. if ($ListOnly){Write-Output "`t*** Running in Listonly mode, no files will be modified ***`n"}
  779. Write-Output ("-"*79)
  780. # If AppendLog switch is present log will be appended, not replaced
  781. if ($AppendLog) {
  782.     ("-"*79) >> $LogFile
  783. } else {
  784.     ("-"*79) > $LogFile
  785. }
  786. "  Deleteold`t::`tScript to delete old files from folders" >> $LogFile
  787. ("-"*79) >> $LogFile
  788. " " >> $LogFile
  789. "   Started  :   $StartTime" >> $LogFile
  790. " " >> $LogFile
  791. "   Folder   :   $FolderPath" >> $LogFile
  792. " " >> $LogFile
  793. "   Switches :   $Switches" >> $LogFile
  794. " " >> $LogFile
  795. ("-"*79) >> $LogFile
  796. " " >> $LogFile
  797. # Define the properties to be selected for the array, if createtime switch is specified
  798. # CreationTime is added to the list of properties, this is to conserve memory space
  799. $SelectProperty = @{'Property'='Fullname','Length','PSIsContainer'}
  800. if ($CreateTime) {
  801. $SelectProperty.Property += 'CreationTime'
  802. } elseif ($LastAccessTime) {
  803.     $SelectProperty.Property += 'LastAccessTime'
  804. } else {
  805. $SelectProperty.Property += 'LastWriteTime'
  806. }
  807. if ($ExcludeFileExtension -or $IncludeFileExtension) {
  808.     $SelectProperty.Property += 'Extension'
  809. }
  810. # Get the complete list of files and save to array
  811. Write-Output "`n   Retrieving list of files and folders from: $FolderPath"
  812. $CheckError = $Error.Count
  813. $FullArray = @(Get-ChildItem -LiteralPath $FolderPath -Recurse -ErrorAction SilentlyContinue -Force | Select-Object @SelectProperty)
  814. # Split the complete list of items into a separate list containing only the files
  815. $FileList = @($FullArray | Where-Object {$_.PSIsContainer -eq $false})
  816. $FolderList = @($FullArray | Where-Object {$_.PSIsContainer -eq $true})
  817. # If the IncludePath parameter is included then this loop will run. This will clear out any path not specified in the
  818. # include parameter. If the ExcludePath parameter is also specified
  819. if ($IncludePath) {
  820.     # If RegExpath has not been specified the script will escape all regular expressions from values specified
  821.     if (!$RegExPath) {
  822.         for ($j=0;$j -lt $IncludePath.Count;$j++) {
  823.     [array]$NewFileList += @($FileList | Where-Object {$_.FullName -match [RegEx]::Escape($IncludePath[$j])})
  824.             [array]$NewFolderList += @($FolderList | Where-Object {$_.FullName -match [RegEx]::Escape($IncludePath[$j])})
  825.         }
  826.     } else {
  827.     # Process the list of files when RegExPath has been specified
  828.         for ($j=0;$j -lt $IncludePath.Count;$j++) {
  829.     [array]$NewFileList += @($FileList | Where-Object {$_.FullName -match $IncludePath[$j]})
  830.             [array]$NewFolderList += @($FolderList | Where-Object {$_.FullName -match $IncludePath[$j]})
  831.         }        
  832.     }
  833.     $FileList = $NewFileList
  834.     $FolderList = $NewFolderList
  835.     $NewFileList=$NewFolderList = $null
  836. }
  837. # If the ExcludePath parameter is included then this loop will run. This will clear out the
  838. # excluded paths for both the filelist.
  839. if ($ExcludePath) {
  840.     # If RegExpath has not been specified the script will escape all regular expressions from values specified
  841.     if (!$RegExPath) {
  842.         for ($j=0;$j -lt $ExcludePath.Count;$j++) {
  843.             $FileList = @($FileList | Where-Object {$_.FullName -notmatch [RegEx]::Escape($ExcludePath[$j])})
  844.             $FolderList = @($FolderList | Where-Object {$_.FullName -notmatch [RegEx]::Escape($ExcludePath[$j])})
  845.     }
  846.     } else {
  847.     # Process the list of files when RegExPath has been specified
  848.         for ($j=0;$j -lt $ExcludePath.Count;$j++) {
  849.     $FileList = @($FileList | Where-Object {$_.FullName -notmatch $ExcludePath[$j]})
  850.             $FolderList = @($FolderList | Where-Object {$_.FullName -notmatch $ExcludePath[$j]})
  851.     }
  852.     }
  853. }
  854. # If the -IncludeFileExtension is specified all filenames matching the criteria specified
  855. if ($IncludeFileExtension) {
  856.     for ($j=0;$j -lt $IncludeFileExtension.Count;$j++) {
  857.         # If no dot is present the dot will be added to the front of the string
  858.         if ($IncludeFileExtension[$j].Substring(0,1) -ne '.') {$IncludeFileExtension[$j] = ".$($IncludeFileExtension[$j])"}
  859.         [array]$NewFileList += @($FileList | Where-Object {$_.Extension -like $IncludeFileExtension[$j]})
  860.     }
  861.     $FileList = $NewFileList
  862.     $NewFileList=$null
  863. }
  864. # If the -ExcludeFileExtension is specified all filenames matching the criteria specified
  865. if ($ExcludeFileExtension) {
  866.     for ($j=0;$j -lt $ExcludeFileExtension.Count;$j++) {
  867.         # If no dot is present the dot will be added to the front of the string
  868.         if ($ExcludeFileExtension[$j].Substring(0,1) -ne '.') {$ExcludeFileExtension[$j] = ".$($ExcludeFileExtension[$j])"}
  869.         $FileList = @($FileList | Where-Object {$_.Extension -notlike $ExcludeFileExtension[$j]})
  870.     }
  871. }
  872. # Catches errors during read stage and writes to log, mostly catches permissions errors. Placed after Exclude/Include portion
  873. # of the script to ensure excluded paths are not generating errors.
  874. $CheckError = $Error.Count - $CheckError
  875. if ($CheckError -gt 0) {
  876. for ($j=0;$j -lt $CheckError;$j++) {
  877.         # Verifies is the error does not match an excluded path, only errors not matching excluded paths will be written to the Log
  878.         if ($ExcludePath) {
  879.             if ($(for ($k=0;$k -lt $ExcludePath.Count;$k++) {$Error[$j].TargetObject -match $ExcludePath[$k].SubString(0,$ExcludePath[$k].Length-2)}) -notcontains $true) {
  880.                 $TempErrorVar = "$($Error[$j].ToString()) ::: $($Error[$j].TargetObject)"
  881.         "`tFAILED ACCESS`t$TempErrorVar" >> $LogFile
  882.             }
  883.     } else {
  884.             $TempErrorVar = "$($Error[$j].ToString()) ::: $($Error[$j].TargetObject)"
  885.     "`tFAILED ACCESS`t$TempErrorVar" >> $LogFile
  886.         }
  887.     }
  888. }
  889. # Counter for prompt output
  890. $AllFileCount = $FileList.Count
  891. # If the -CreateTime switch has been used the script looks for file creation time rather than
  892. # file modified/lastwrite time
  893. if ($CreateTime) {
  894. $FileList = @($FileList | Where-Object {$_.CreationTime -le $LastWrite})
  895. } elseif ($LastAccessTime) {
  896.     $FileList = @($FileList | Where-Object {$_.LastAccessTime -le $LastWrite})
  897. } else {
  898.     $FileList = @($FileList | Where-Object {$_.LastWriteTime -le $LastWrite})
  899. }
  900. # If the ExcludeDate parameter is specified the query is converted by the ConvertFrom-Query function. The
  901. # output of that table is a hashtable that is splatted to the ConvertTo-DateObject function which returns
  902. # an array of dates. All files that match a date in the returned array will be excluded from deletion which
  903. # allows for more specific exclusions.
  904. if ($ExcludeDate) {
  905.     $SplatDate = ConvertFrom-DateQuery $ExcludeDate
  906.     $ExcludedDates = @(ConvertTo-DateObject @SplatDate | Select-Object -Unique | Sort-Object -Descending)
  907.     if ($CreateTime) {
  908.         $FileList = @($FileList | Where-Object {$ExcludedDates -notcontains $_.CreationTime.Date})
  909.     } elseif ($LastAccessTime) {
  910.     $FileList = @($FileList | Where-Object {$_.LastAccessTime -le $LastWrite})
  911.     } else {
  912.         $FileList = @($FileList | Where-Object {$ExcludedDates -notcontains $_.LastWriteTime.Date})
  913.     }
  914.     [string]$DisplayExcludedDates = for ($j=0;$j -lt $ExcludedDates.Count;$j++) {
  915.         if ($j -eq 0) {
  916.             "`n   ExcludedDates: $($ExcludedDates[$j].ToString('yyyy-MM-dd'))"
  917.         } else {
  918.             $ExcludedDates[$j].ToString('yyyy-MM-dd')
  919.         }
  920.         # After every fifth date start on the next line
  921.         if ((($j+1) % 6) -eq 0) {"`n`t`t "}
  922.     }
  923.     $DisplayExcludedDates
  924. }
  925. # Defines the list of folders, either a complete list of all folders if -CleanFolders
  926. # was specified or just the folders containing old files. The -NoFolder switch will ensure
  927. # the folder structure is not modified and only files are deleted.
  928. if ($CleanFolders) {
  929.     # Uses the FolderList variable defined at the start of the script, including any exclusions/inclusions
  930. } elseif ($NoFolder) {
  931.     $FolderList = @()
  932. } else {
  933.     $FolderList = @($FileList | ForEach-Object {
  934.         Split-Path -Path $_.FullName} |
  935.         Select-Object -Unique | ForEach-Object {
  936.             Get-Item -LiteralPath $_ -ErrorAction SilentlyContinue | Select-Object @SelectProperty})
  937. }
  938. # Clear original array containing files and folders and create array with list of older files
  939. $FullArray = ""
  940. # Write totals to console
  941. Write-Output "`n   Files`t: $AllFileCount`n   Folders`t: $($FolderList.Count) `n   Old files`t: $($FileList.Count)"
  942. # Execute main functions of script
  943. if (-not $ListOnly) {
  944.     Write-Output "`n   Starting with removal of old files..."
  945. } else {
  946.     Write-Output "`n   Listing files..."
  947. }
  948. F_Deleteoldfiles
  949. if (-not $ListOnly) {
  950.     Write-Output "   Finished deleting files`n"
  951. } else {
  952.     Write-Output "   Finished listing files`n"
  953. }
  954. if (-not $ListOnly) {
  955. Write-Output "   Check/remove empty folders started..."
  956. F_Checkforemptyfolder
  957. Write-Output "   Empty folders deleted`n"
  958. }
  959. # Pre-format values for footer
  960. $TimeTaken = ((Get-Date) - $StartDate).ToString().SubString(0,8)
  961. $FilesSize = $FilesSize/1MB
  962. [string]$FilesSize = $FilesSize.ToString()
  963. $FailedSize = $FailedSize/1MB
  964. [string]$FailedSize = $FailedSize.ToString()
  965. $EndDate = "$((Get-Date).ToShortDateString()), $((Get-Date).ToLongTimeString())"
  966. # Write footer to log and output to console
  967. Write-Output ($Footer = @"
  968. $("-"*79)
  969.    Files               : $FilesNumber
  970.    Filesize(MB)        : $FilesSize
  971.    Files Failed        : $FilesFailed
  972.    Failedfile Size(MB) : $FailedSize
  973.    Folders             : $FoldersNumber
  974.    Folders Failed      : $FoldersFailed
  975.    Finished Time       : $EndDate
  976.    Total Time          : $TimeTaken
  977. $("-"*79)
  978. "@)
  979. Out-File -FilePath $LogFile -Append -InputObject $Footer
  980. # Section of script that emails the logfile if required parameters are specified.
  981. if ($EmailSplat) {
  982.     Send-MailMessage @EmailSplat
  983. }
  984. # Clean up variables at end of script
  985. $FileList=$FolderList = $null
复制代码





欢迎光临 批处理之家 (http://bathome.net./) Powered by Discuz! 7.2