找回密码
 注册
搜索
[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
查看: 14679|回复: 0

[转载代码] PowerShell删除指定天数之前的文件

[复制链接]
发表于 2013-11-8 13:43:38 | 显示全部楼层 |阅读模式
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.        
  8. .PARAMETER FolderPath
  9. The path that will be recusively scanned for old files.

  10. .PARAMETER Fileage
  11. Filter for age of file, entered in days. Use -1 for all files to be removed.
  12.        
  13. .PARAMETER LogFile
  14. Specifies the full path and filename of the logfile. When the LogFile parameter is used in combination with -autolog only the path is required.

  15. .PARAMETER AutoLog
  16. 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:
  17. "Autolog_<FolderPath><dd-MM-yyyy_HHmm.ss>.log"

  18. .PARAMETER ExcludePath
  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.

  20. .PARAMETER IncludePath
  21. 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.

  22. .PARAMETER RegExPath
  23. 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.

  24. .PARAMETER ExcludeFileExtension
  25. 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.

  26. .PARAMETER IncludeFileExtension
  27. 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.

  28. .PARAMETER EmailTo
  29. 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.

  30. .PARAMETER EmailFrom
  31. 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.

  32. .PARAMETER EmailSmtpServer
  33. Should be used in conjunction with the EmailTo and EmailFrom parameters, this parameter takes the fully qualified domain name of your smtp server.

  34. .PARAMETER EmailSubject
  35. 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'

  36. .PARAMETER ExcludeDate
  37. 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.
  38. Query examples:
  39. Week:
  40. 'Week,sat,-1'
  41. Will list all saturday until the LimitYear maximum is reached
  42. 'Week,wed,5'
  43. Will list the last 5 wednesdays

  44. Month:
  45. 'Month,first,4'
  46. Will list the first day of the last four months
  47. 'Month,last,-1'
  48. 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.
  49. 'Month,30,3'
  50. 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.
  51. 'Month,31,-1'
  52. 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.
  53. 'Month,15,4','Month,last,-1'
  54. 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.

  55. Quarter:
  56. 'Quarter,first,-1'
  57. Will list the first day of a quarter until the LimitYear maximum is reached
  58. 'Quarter,last,6'
  59. 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.
  60. 'Quarter,91,5'
  61. 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
  62. 'Quarter,92,-1'
  63. 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

  64. Year:
  65. 'Year,last,4'
  66. Will list the 31st of december for the last 4 years
  67. 'Year,first,-1'
  68. Will list the 1st of january until the Limityear maximum has been reached
  69. 'Year,15,-1'
  70. Will list the 15 of january until the LimitYear maximum has been reached
  71. 'Year,366,5'
  72. Will list only the 366st day, only the last day of the last 5 leap years

  73. Specific Date:
  74. 'Date,2010-05-15'
  75. Will list 15th of may 2010
  76. 'Date,2012/12/12'
  77. Will list 12th of december 2012

  78. Date Ranges:
  79. 'DateRange,2010-05-05,10'
  80. Will list 10 dates, starting at the 5th of May 2010 continuing up until the 14th of May 2010

  81. 'LimitYear,2008'
  82. Will place the limit of LimitYear to 2008, the default value of this parameter is 2010.

  83. 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:
  84. 'Week,Fri,10','Year,last,-1','LimitYear,1950'
  85. Will list the last 10 fridays and the 31st of december for all years until the LimitYear is reached
  86. 'Week,Thu,4','Month,last,-1','Quarter,first,6','Year,last,10','LimitYear,2012','Date,1990-12-31','Date,1995-5-31'
  87. 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.

  88. .PARAMETER ListOnly
  89. 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.

  90. .PARAMETER VerboseLog
  91. Logs all delete operations to log, default behaviour of the script is to log failed only.

  92. .PARAMETER AppendLog
  93. 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.

  94. .PARAMETER CreateTime
  95. Deletes files based on CreationTime, the default behaviour of the script is to delete based on LastWriteTime.

  96. .PARAMETER LastAccessTime
  97. Deletes files based on LastAccessTime, the default behaviour of the script is to delete based on LastWriteTime.

  98. .PARAMETER CleanFolders
  99. 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.

  100. .PARAMETER NoFolder
  101. If this switch is specified only files will be deleted and the existing folder will be retained.

  102. .NOTES   
  103. Name: deleteold.ps1
  104. Author: Jaap Brasser
  105. Version: 1.9.2
  106. DateUpdated: 2013-09-26

  107. .LINK
  108. http://www.jaapbrasser.com

  109. .EXAMPLE   
  110. .\deleteold.ps1 -FolderPath H:\scripts -FileAge 100 -ListOnly -LogFile H:\log.log

  111. Description:
  112. Searches through the H:\scripts folder and writes a logfile containing files that were last modified 100 days ago and older.

  113. .EXAMPLE
  114. .\deleteold.ps1 -FolderPath H:\scripts -FileAge 30 -LogFile H:\log.log -VerboseLog

  115. Description:
  116. 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.

  117. .EXAMPLE
  118. .\deleteold.ps1 -FolderPath C:\docs -FileAge 30 -LogFile H:\log.log -ExcludePath "C:\docs\finance","C:\docs\hr"

  119. Description:
  120. Searches through the C:\docs folder and deletes files, exluding the finance and hr folders in C:\docs.

  121. .EXAMPLE
  122. .\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"

  123. Description:
  124. 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.

  125. .EXAMPLE
  126. .\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'

  127. Description:
  128. 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

  129. .EXAMPLE
  130. .\deleteold.ps1 -FolderPath C:\Folder -FileAge 60 -LogFile H:\log.log -IncludePath .*images.* -RegExPath

  131. Description:
  132. Delete files older than 60 days and only delete files that contain 'images' in their path name.

  133. .EXAMPLE
  134. .\deleteold.ps1 -FolderPath C:\Folder -FileAge 45 -LastAccessTime -LogFile H:\log.log

  135. Description:
  136. Delete files that have not been access for more than 45 days.

  137. .EXAMPLE
  138. PowerShell.exe deleteold.ps1 -FolderPath 'H:\admin_jaap' -FileAge 10 -LogFile C:\log -AutoLog

  139. Description:
  140. 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.

  141. .EXAMPLE
  142. .\deleteold.ps1 -FolderPath C:\docs -FileAge 30 -logfile h:\log.log -CreateTime -NoFolder

  143. Description:
  144. Deletes all files that were created 30 days ago or before in the C:\docs folder. No folders are deleted.

  145. .EXAMPLE
  146. .\deleteold.ps1 -FolderPath C:\docs -FileAge 30 -logfile h:\log.log -CreateTime -CleanFolders

  147. Description:
  148. 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.

  149. .EXAMPLE
  150. .\deleteold.ps1 -folderpath c:\users\jaapbrasser\desktop -fileage 10 -log c:\log.txt -autolog -verboselog -IncludeFileExtension '.xls*','.doc*'

  151. Description:
  152. 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.

  153. .EXAMPLE
  154. .\deleteold.ps1 -folderpath c:\users\jaapbrasser\desktop -fileage 10 -log c:\log.txt -autolog -verboselog -ExcludeFileExtension .xls

  155. Description:
  156. 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.

  157. .EXAMPLE
  158. .\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'

  159. Description:
  160. 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.

  161. .EXAMPLE   
  162. .\deleteold.ps1 -FolderPath H:\scripts -FileAge 100 -ListOnly -LogFile H:\log.log -ExcludeDate 'DateRange,2005-05-16,8'

  163. Description:
  164. 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.

  165. .EXAMPLE
  166. .\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

  167. Description:
  168. 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.
  169. #>

  170. #region Parameters
  171. param(
  172.     [string]$FolderPath,
  173.         [string]$FileAge,
  174.         [string]$LogFile,
  175.     [string[]]$ExcludePath,
  176.     [string[]]$IncludePath,
  177.         [string[]]$ExcludeFileExtension,
  178.     [string[]]$IncludeFileExtension,
  179.     [string[]]$ExcludeDate,
  180.     [string[]]$EmailTo,
  181.     [string]$EmailFrom,
  182.     [string]$EmailSmtpServer,
  183.     [string]$EmailSubject,
  184.     [switch]$ListOnly,
  185.         [switch]$VerboseLog,
  186.         [switch]$AutoLog,
  187.     [switch]$AppendLog,
  188.         [switch]$CreateTime,
  189.     [switch]$LastAccessTime,
  190.     [switch]$CleanFolders,
  191.     [switch]$NoFolder,
  192.     [switch]$RegExPath
  193. )
  194. #endregion

  195. #region Functions
  196. # Function to convert the query provided in -ExcludeDate to a format that can be parsed by the ConvertTo-DateObject function
  197. function ConvertFrom-DateQuery {
  198. param (
  199.     $Query
  200. )
  201.     try {
  202.         $CsvQuery = Convertfrom-Csv -InputObject $Query -Delimiter ',' -Header "Type","Day","Repeat"
  203.         $ConvertCsvSuccess = $true
  204.     } catch {
  205.         Write-Warning "Query is in incorrect format, please supply query in proper format"
  206.         $ConvertCsvSuccess = $false
  207.     }
  208.     if ($ConvertCsvSuccess) {
  209.         $Check=$HashOutput = @{}
  210.         foreach ($Entry in $CsvQuery) {
  211.             switch ($Entry.Type) {
  212.                 'week' {
  213.                     # Convert named dates to correct format
  214.                     switch ($Entry.Day)
  215.                     {
  216.                         # DayOfWeek starts count at 0, referring to the [datetime] property DayOfWeek
  217.                         'sun' {
  218.                             $HashOutput.DayOfWeek = 0
  219.                             $HashOutput.WeekRepeat = $Entry.Repeat
  220.                         }
  221.                         'mon' {
  222.                             $HashOutput.DayOfWeek = 1
  223.                             $HashOutput.WeekRepeat = $Entry.Repeat
  224.                         }
  225.                         'tue' {
  226.                             $HashOutput.DayOfWeek = 2
  227.                             $HashOutput.WeekRepeat = $Entry.Repeat
  228.                         }
  229.                         'wed' {
  230.                             $HashOutput.DayOfWeek = 3
  231.                             $HashOutput.WeekRepeat = $Entry.Repeat
  232.                         }
  233.                         'thu' {
  234.                             $HashOutput.DayOfWeek = 4
  235.                             $HashOutput.WeekRepeat = $Entry.Repeat
  236.                         }
  237.                         'fri' {
  238.                             $HashOutput.DayOfWeek = 5
  239.                             $HashOutput.WeekRepeat = $Entry.Repeat
  240.                         }
  241.                         'sat' {
  242.                             $HashOutput.DayOfWeek = 6
  243.                             $HashOutput.WeekRepeat = $Entry.Repeat
  244.                         }
  245.                         Default {$Check.WeekSuccess = $false}
  246.                     }
  247.                 }
  248.                 'month' {
  249.                     # Convert named dates to correct format
  250.                     switch ($Entry.Day)
  251.                     {
  252.                         # DayOfMonth starts count at 0, referring to the last day of the month with zero
  253.                         'first' {
  254.                             [array]$HashOutput.DayOfMonth += 1
  255.                             [array]$HashOutput.MonthRepeat += $Entry.Repeat
  256.                         }
  257.                         'last' {
  258.                             [array]$HashOutput.DayOfMonth += 0
  259.                             [array]$HashOutput.MonthRepeat += $Entry.Repeat
  260.                         }
  261.                         {(1..31) -contains $_} {
  262.                             [array]$HashOutput.DayOfMonth += $Entry.Day
  263.                             [array]$HashOutput.MonthRepeat += $Entry.Repeat
  264.                         }
  265.                         Default {$Check.MonthSuccess = $false}
  266.                     }
  267.                 }
  268.                 'quarter' {
  269.                     # Count the number of times the quarter argument is used, used in final check of values
  270.                     $QuarterCount++

  271.                     # Convert named dates to correct format
  272.                     switch ($Entry.Day)
  273.                     {
  274.                         # DayOfMonth starts count at 0, referring to the last day of the month with zero
  275.                         'first' {
  276.                             $HashOutput.DayOfQuarter = 1
  277.                             $HashOutput.QuarterRepeat = $Entry.Repeat
  278.                         }
  279.                         'last' {
  280.                             $HashOutput.DayOfQuarter = 0
  281.                             $HashOutput.QuarterRepeat = $Entry.Repeat
  282.                         }
  283.                         {(1..92) -contains $_} {
  284.                             $HashOutput.DayOfQuarter = $Entry.Day
  285.                             $HashOutput.QuarterRepeat = $Entry.Repeat
  286.                         }
  287.                         Default {$Check.QuarterSuccess = $false}
  288.                     }
  289.                 }
  290.                 'year' {
  291.                     # Convert named dates to correct format
  292.                     switch ($Entry.Day)
  293.                     {
  294.                         # DayOfMonth starts count at 0, referring to the last day of the month with zero
  295.                         'first' {
  296.                             $HashOutput.DayOfYear = 1
  297.                             $HashOutput.DayOfYearRepeat = $Entry.Repeat
  298.                         }
  299.                         'last' {
  300.                             $HashOutput.DayOfYear = 0
  301.                             $HashOutput.DayOfYearRepeat = $Entry.Repeat
  302.                         }
  303.                         {(1..366) -contains $_} {
  304.                             $HashOutput.DayOfYear = $Entry.Day
  305.                             $HashOutput.DayOfYearRepeat = $Entry.Repeat
  306.                         }
  307.                         Default {$Check.YearSuccess = $false}
  308.                     }
  309.                 }
  310.                 'date' {
  311.                     # Verify if the date is in the correct format
  312.                     switch ($Entry.Day)
  313.                     {
  314.                         {try {[DateTime]"$($Entry.Day)"} catch{}} {
  315.                             [array]$HashOutput.DateDay += $Entry.Day
  316.                         }
  317.                         Default {$Check.DateSuccess = $false}
  318.                     }
  319.                 }

  320.                 'daterange' {
  321.                     # Verify if the date is in the correct format
  322.                     switch ($Entry.Day)
  323.                     {
  324.                         {try {[DateTime]"$($Entry.Day)"} catch{}} {
  325.                             $HashOutput.DateRange += $Entry.Day
  326.                             $HashOutput.DateRangeRepeat += $Entry.Repeat
  327.                         }
  328.                         Default {$Check.DateRangeSuccess = $false}
  329.                     }
  330.                 }

  331.                 'limityear' {
  332.                     switch ($Entry.Day)
  333.                     {
  334.                         {(1000..2100) -contains $_} {
  335.                             $HashOutput.LimitYear = $Entry.Day
  336.                         }
  337.                         Default {$Check.LimitYearSuccess = $false}
  338.                     }
  339.                 }
  340.                 Default {
  341.                     $QueryContentCorrect = $false
  342.                 }
  343.             }
  344.         }
  345.         $HashOutput
  346.     }
  347. }

  348. # Function that outputs an array of date objects that can be used to exclude certain files from deletion
  349. function ConvertTo-DateObject {
  350. param(
  351.     [validaterange(0,6)]
  352.     $DayOfWeek,
  353.     [int]$WeekRepeat=1,
  354.     [validaterange(0,31)]
  355.     $DayOfMonth,
  356.     $MonthRepeat=1,
  357.     [validaterange(0,92)]
  358.     $DayOfQuarter,
  359.     [int]$QuarterRepeat=1,
  360.     [validaterange(0,366)]
  361.     $DayOfYear,
  362.     [int]$DayOfYearRepeat=1,
  363.     $DateDay,
  364.     $DateRange,
  365.     [int]$DateRangeRepeat=1,
  366.     [validaterange(1000,2100)]
  367.     [int]$LimitYear = 2010
  368. )
  369.     # Define variable
  370.     $CurrentDate = Get-Date

  371.     if ($DayOfWeek -ne $null) {
  372.         $CurrentWeekDayInt = $CurrentDate.DayOfWeek.value__

  373.             # Loop runs for number of times specified in the WeekRepeat parameter
  374.             for ($j = 0; $j -lt $WeekRepeat; $j++)
  375.                 {
  376.                     $CheckDate = $CurrentDate.Date.AddDays(-((7*$j)+$CurrentWeekDayInt-$DayOfWeek))

  377.                     # Only display date if date is larger than current date, this is to exclude dates in the current week
  378.                     if ($CheckDate -le $CurrentDate) {
  379.                         $CheckDate
  380.                     } else {
  381.                         # Increase weekrepeat, to ensure the correct amount of repeats are executed when date returned is
  382.                         # higher than current date
  383.                         $WeekRepeat++
  384.                     }
  385.                 }
  386.             
  387.             # Loop runs until $LimitYear parameter is exceeded
  388.                         if ($WeekRepeat -eq -1) {
  389.                 $j=0
  390.                 do {
  391.                     $CheckDate = $CurrentDate.AddDays(-((7*$j)+$CurrentWeekDayInt-$DayOfWeek))
  392.                     $j++

  393.                     # Only display date if date is larger than current date, this is to exclude dates in the current week
  394.                     if ($CheckDate -le $CurrentDate) {
  395.                         $CheckDate
  396.                     }
  397.                 } while ($LimitYear -le $CheckDate.Adddays(-7).Year)
  398.             }
  399.         }

  400.     if ($DayOfMonth -ne $null) {
  401.         for ($MonthCnt = 0; $MonthCnt -lt $DayOfMonth.Count; $MonthCnt++) {
  402.             # Loop runs for number of times specified in the MonthRepeat parameter
  403.             for ($j = 0; $j -lt $MonthRepeat[$MonthCnt]; $j++)
  404.                 {
  405.                     $CheckDate = $CurrentDate.Date.AddMonths(-$j).AddDays($DayOfMonth[$MonthCnt]-$CurrentDate.Day)

  406.                     # Only display date if date is larger than current date, this is to exclude dates ahead of the current date and
  407.                     # to list only output the possible dates. If a value of 29 or higher is specified as a DayOfMonth value
  408.                     # only possible dates are listed.
  409.                     if ($CheckDate -le $CurrentDate -and $(if ($DayOfMonth[$MonthCnt] -ne 0) {$CheckDate.Day -eq $DayOfMonth[$MonthCnt]} else {$true})) {
  410.                         $CheckDate
  411.                     } else {
  412.                         # Increase MonthRepeat integer, to ensure the correct amount of repeats are executed when date returned is
  413.                         # higher than current date
  414.                         $MonthRepeat[$MonthCnt]++
  415.                     }
  416.                 }
  417.             
  418.             # Loop runs until $LimitYear parameter is exceeded
  419.                     if ($MonthRepeat[$MonthCnt] -eq -1) {
  420.                 $j=0
  421.                 do {
  422.                     $CheckDate = $CurrentDate.Date.AddMonths(-$j).AddDays($DayOfMonth[$MonthCnt]-$CurrentDate.Day)
  423.                     $j++

  424.                     # Only display date if date is larger than current date, this is to exclude dates ahead of the current date and
  425.                     # to list only output the possible dates. For example if a value of 29 or higher is specified as a DayOfMonth value
  426.                     # only possible dates are listed.
  427.                     if ($CheckDate -le $CurrentDate -and $(if ($DayOfMonth[$MonthCnt] -ne 0) {$CheckDate.Day -eq $DayOfMonth[$MonthCnt]} else {$true})) {
  428.                         $CheckDate
  429.                     }
  430.                 } while ($LimitYear -le $CheckDate.Adddays(-31).Year)
  431.             }
  432.         }
  433.     }

  434.     if ($DayOfQuarter -ne $null) {
  435.         # Set quarter int to current quarter value $QuarterInt
  436.         $QuarterInt = [int](($CurrentDate.Month+1)/3)
  437.         $QuarterYearInt = $CurrentDate.Year
  438.         $QuarterLoopCount = $QuarterRepeat
  439.         $j = 0
  440.         
  441.         do {
  442.             switch ($QuarterInt) {
  443.                 1 {
  444.                     $CheckDate = ([DateTime]::ParseExact("$($QuarterYearInt)0101",'yyyyMMdd',$null)).AddDays($DayOfQuarter-1)
  445.                     
  446.                     # Check for number of days in the 1st quarter, this depends on leap years
  447.                     $DaysInFeb = ([DateTime]::ParseExact("$($QuarterYearInt)0301",'yyyyMMdd',$null)).AddDays(-1).Day
  448.                     $DaysInCurrentQuarter = 31+$DaysInFeb+31
  449.                         
  450.                     # If the number of days is larger that the total number of days in this quarter the quarter will be excluded
  451.                     if ($DayOfQuarter -gt $DaysInCurrentQuarter) {
  452.                         $CheckDate = $null
  453.                     }

  454.                     # This check is built-in to return the date last date of the current quarter, to ensure consistent results
  455.                     # in case the command is executed on the last day of a quarter
  456.                     if ($DayOfQuarter -eq 0) {
  457.                         $CheckDate = [DateTime]::ParseExact("$($QuarterYearInt)0331",'yyyyMMdd',$null)
  458.                     }

  459.                     $QuarterInt = 4
  460.                     $QuarterYearInt--
  461.                 }
  462.                 2 {
  463.                     $CheckDate = ([DateTime]::ParseExact("$($QuarterYearInt)0401",'yyyyMMdd',$null)).AddDays($DayOfQuarter-1)
  464.                         
  465.                     # Check for number of days in the 2nd quarter
  466.                     $DaysInCurrentQuarter = 30+31+30
  467.                         
  468.                     # If the number of days is larger that the total number of days in this quarter the quarter will be excluded
  469.                     if ($DayOfQuarter -gt $DaysInCurrentQuarter) {
  470.                         $CheckDate = $null
  471.                     }

  472.                     # This check is built-in to return the date last date of the current quarter, to ensure consistent results
  473.                     # in case the command is executed on the last day of a quarter                       
  474.                     if ($DayOfQuarter -eq 0) {
  475.                         $CheckDate = [DateTime]::ParseExact("$($QuarterYearInt)0630",'yyyyMMdd',$null)
  476.                     }
  477.                         
  478.                     $QuarterInt = 1
  479.                 }
  480.                 3 {
  481.                     $CheckDate = ([DateTime]::ParseExact("$($QuarterYearInt)0701",'yyyyMMdd',$null)).AddDays($DayOfQuarter-1)
  482.                         
  483.                     # Check for number of days in the 3rd quarter
  484.                     $DaysInCurrentQuarter = 31+31+30
  485.                         
  486.                     # If the number of days is larger that the total number of days in this quarter the quarter will be excluded
  487.                     if ($DayOfQuarter -gt $DaysInCurrentQuarter) {
  488.                         $CheckDate = $null
  489.                     }
  490.                         
  491.                     # This check is built-in to return the date last date of the current quarter, to ensure consistent results
  492.                     # in case the command is executed on the last day of a quarter                       
  493.                     if ($DayOfQuarter -eq 0) {
  494.                         $CheckDate = [DateTime]::ParseExact("$($QuarterYearInt)0930",'yyyyMMdd',$null)
  495.                     }

  496.                     $QuarterInt = 2
  497.                 }
  498.                 4 {
  499.                     $CheckDate = ([DateTime]::ParseExact("$($QuarterYearInt)1001",'yyyyMMdd',$null)).AddDays($DayOfQuarter-1)
  500.                         
  501.                     # Check for number of days in the 4th quarter
  502.                     $DaysInCurrentQuarter = 31+30+31
  503.                         
  504.                     # If the number of days is larger that the total number of days in this quarter the quarter will be excluded
  505.                     if ($DayOfQuarter -gt $DaysInCurrentQuarter) {
  506.                         $CheckDate = $null
  507.                     }

  508.                     # This check is built-in to return the date last date of the current quarter, to ensure consistent results
  509.                     # in case the command is executed on the last day of a quarter                       
  510.                     if ($DayOfQuarter -eq 0) {
  511.                         $CheckDate = [DateTime]::ParseExact("$($QuarterYearInt)1231",'yyyyMMdd',$null)
  512.                     }                        
  513.                     $QuarterInt = 3
  514.                 }
  515.             }

  516.             # Only display date if date is larger than current date, and only execute check if $CheckDate is not equal to $null
  517.             if ($CheckDate -le $CurrentDate -and $CheckDate -ne $null) {
  518.                     
  519.                 # Only display the date if it is not further in the past than the limit year
  520.                 if ($CheckDate.Year -ge $LimitYear -and $QuarterRepeat -eq -1) {
  521.                     $CheckDate
  522.                 }

  523.                 # If the repeat parameter is not set to -1 display results regardless of limit year                    
  524.                 if ($QuarterRepeat -ne -1) {
  525.                     $CheckDate
  526.                     $j++
  527.                 } else {
  528.                     $QuarterLoopCount++
  529.                 }
  530.             }
  531.             # Added if statement to catch errors regarding
  532.         } while ($(if ($QuarterRepeat -eq -1) {$LimitYear -le $(if ($CheckDate) {$CheckDate.Year} else {9999})}
  533.                 else {$j -lt $QuarterLoopCount}))
  534.     }

  535.     if ($DayOfYear -ne $null) {
  536.         $YearLoopCount = $DayOfYearRepeat
  537.         $YearInt = $CurrentDate.Year
  538.         $j = 0

  539.         # Mainloop containing the loop for selecting a day of a year
  540.         do {
  541.             $CheckDate = ([DateTime]::ParseExact("$($YearInt)0101",'yyyyMMdd',$null)).AddDays($DayOfYear-1)
  542.             
  543.             # 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
  544.             if ($DayOfYear -eq 0) {
  545.                 $CheckDate = $CheckDate.AddYears(1)
  546.             }
  547.             
  548.             # Set checkdate to null to allow for selection of last day of leap year
  549.             if (($DayOfYear -eq 366) -and !([DateTime]::IsLeapYear($YearInt))) {
  550.                 $CheckDate = $null
  551.             }

  552.             # Only display date if date is larger than current date, and only execute check if $CheckDate is not equal to $null
  553.             if ($CheckDate -le $CurrentDate -and $CheckDate -ne $null) {
  554.                 # Only display the date if it is not further in the past than the limit year
  555.                 if ($CheckDate.Year -ge $LimitYear -and $DayOfYearRepeat -eq -1) {
  556.                     $CheckDate
  557.                 }

  558.                 # If the repeat parameter is not set to -1 display results regardless of limit year
  559.                 if ($DayOfYearRepeat -ne -1) {
  560.                     $CheckDate
  561.                     $j++
  562.                 } else {
  563.                     $YearLoopCount++
  564.                 }
  565.             }
  566.             $YearInt--
  567.         } while ($(if ($DayOfYearRepeat -eq -1) {$LimitYear -le $(if ($CheckDate) {$CheckDate.Year} else {9999})}
  568.                 else {$j -lt $YearLoopCount}))
  569.     }

  570.     if ($DateDay -ne $null) {
  571.         foreach ($Date in $DateDay) {
  572.             try {
  573.                 $CheckDate = [DateTime]::ParseExact($Date,'yyyy-MM-dd',$null)
  574.             } catch {
  575.                 try {
  576.                     $CheckDate = [DateTime]::ParseExact($Date,'yyyy\/MM\/dd',$null)
  577.                 } catch {}
  578.             }
  579.             
  580.             if ($CheckDate -le $CurrentDate) {
  581.                 $CheckDate
  582.             }
  583.             $CheckDate=$null
  584.         }
  585.     }

  586.     if ($DateRange -ne $null) {
  587.         $CheckDate=$null
  588.         try {
  589.             $CheckDate = [DateTime]::ParseExact($DateRange,'yyyy-MM-dd',$null)
  590.         } catch {
  591.             try {
  592.                 $CheckDate = [DateTime]::ParseExact($DateRange,'yyyy\/MM\/dd',$null)
  593.             } catch {}
  594.         }
  595.         if ($CheckDate) {
  596.             for ($k = 0; $k -lt $DateRangeRepeat; $k++) {
  597.                 if ($CheckDate -le $CurrentDate) {
  598.                     $CheckDate
  599.                 }
  600.                 $CheckDate = $CheckDate.AddDays(1)
  601.             }
  602.         }
  603.     }
  604. }

  605. # Function that is triggered when the -autolog switch is active
  606. function F_Autolog {
  607.         # Gets date and reformats to be used in log filename
  608.         $TempDate = (get-date).ToString("dd-MM-yyyy_HHmm.ss")
  609.         # Reformats $FolderPath so it can be used in the log filename
  610.         $TempFolderPath = $FolderPath -replace '\\','_'
  611.         $TempFolderPath = $TempFolderPath -replace ':',''
  612.         $TempFolderPath = $TempFolderPath -replace ' ',''
  613.         # Checks if the logfile is either pointing at a folder or a logfile and removes
  614.         # Any trailing backslashes
  615.         $TestLogPath = Test-Path $LogFile -PathType Container
  616.         if (-not $TestLogPath) {
  617.         $LogFile = Split-Path $LogFile -Erroraction SilentlyContinue
  618.     }
  619.         if ($LogFile.SubString($LogFile.Length-1,1) -eq "") {
  620.         $LogFile = $LogFile.SubString(0,$LogFile.Length-1)
  621.     }
  622.         # Combines the date and the path scanned into the log filename
  623.         $script:LogFile = "$LogFile\Autolog_$TempFolderPath$TempDate.log"
  624. }

  625. # Function which contains the loop in which files are deleted. If a file fails to be deleted
  626. # an error is logged and the error message is written to the log.
  627. # $count is used to speed up the delete fileloop and will also be used for other large loops in the script
  628. function F_Deleteoldfiles {
  629.         $Count = $FileList.Count
  630.         for ($j=0;$j -lt $Count;$j++) {
  631.                 $TempFile = $FileList[$j].FullName
  632.                 $TempSize = $FileList[$j].Length
  633.                 if (-not $ListOnly) {Remove-Item -LiteralPath $Tempfile -Force -ErrorAction SilentlyContinue}
  634.                 if (-not $?) {
  635.                         $TempErrorVar = "$($Error[0].ToString()) ::: $($Error[0].targetobject)"
  636.                         "`tFAILED FILE`t`t$TempErrorVar" >> $LogFile
  637.                         $script:FilesFailed++
  638.                         $script:FailedSize+=$TempSize
  639.                 } else {
  640.                         if (-not $ListOnly) {
  641.                 $script:FilesNumber++;$script:FilesSize+=$TempSize
  642.                 if ($VerboseLog) {
  643.                     switch ($true) {
  644.                         {$CreateTime} {"`tDELETED FILE`t$($FileList[$j].CreationTime.ToString('yyyy-MM-dd hh:mm:ss'))`t$($FileList[$j].Length.ToString().PadLeft(15))`t$tempfile" >> $LogFile}
  645.                         {$LastAccessTime} {"`tDELETED FILE`t$($FileList[$j].LastAccessTime.ToString('yyyy-MM-dd hh:mm:ss'))`t$($FileList[$j].Length.ToString().PadLeft(15))`t$tempfile" >> $LogFile}
  646.                         Default {"`tDELETED FILE`t$($FileList[$j].LastWriteTime.ToString('yyyy-MM-dd hh:mm:ss'))`t$($FileList[$j].Length.ToString().PadLeft(15))`t$tempfile" >> $LogFile}
  647.                     }
  648.                 }
  649.             }
  650.                 }
  651.                 if($ListOnly) {
  652.             if ($VerboseLog) {
  653.                 switch ($true) {
  654.                     {$CreateTime} {"`tLISTONLY`t$($FileList[$j].CreationTime.ToString('yyyy-MM-dd hh:mm:ss'))`t$($FileList[$j].Length.ToString().PadLeft(15))`t$tempfile" >> $LogFile}
  655.                     {$LastAccessTime} {"`tLISTONLY`t$($FileList[$j].LastAccessTime.ToString('yyyy-MM-dd hh:mm:ss'))`t$($FileList[$j].Length.ToString().PadLeft(15))`t$tempfile" >> $LogFile}
  656.                     Default {"`tLISTONLY`t$($FileList[$j].LastWriteTime.ToString('yyyy-MM-dd hh:mm:ss'))`t$($FileList[$j].Length.ToString().PadLeft(15))`t$tempfile" >> $LogFile}
  657.                 }
  658.             } else {
  659.                 "`tLISTONLY`t$TempFile" >> $LogFile
  660.             }
  661.                         $script:FilesNumber++
  662.                         $script:FilesSize+=$TempSize
  663.                 }
  664.         }
  665. }

  666. # Checks whether folder is empty and uses temporary variables
  667. # Main loop goes through list of folders, only deleting the empty folders
  668. # The if(-not $tempfolder) is the verification whether the folder is empty
  669. function F_Checkforemptyfolder {
  670.         $FolderList = @($FolderList | sort-object @{Expression={$_.FullName.Length}; Ascending=$false})
  671.         $Count = $FolderList.Count
  672.         for ($j=0;$j -lt $Count;$j++) {
  673.                 $TempFolder = Get-ChildItem -LiteralPath $FolderList[$j].FullName -ErrorAction SilentlyContinue -Force
  674.                 if (-not $TempFolder) {
  675.                     $TempName = $FolderList[$j].FullName
  676.                     Remove-Item -LiteralPath $TempName -Force -Recurse -ErrorAction SilentlyContinue
  677.                         if(-not $?) {
  678.                                 $TempErrorVar = "$($Error[0].ToString()) ::: $($Error[0].targetobject)"
  679.                                 "`tFAILED FOLDER`t$TempErrorVar" >> $LogFile
  680.                                 $script:FoldersFailed++
  681.                         } else {
  682.                                 if ($VerboseLog) {
  683.                     switch ($true) {
  684.                         {$CreateTime} {"`tDELETED FOLDER`t$($FolderList[$j].CreationTime.ToString('yyyy-MM-dd hh:mm:ss'))`t`t`t$TempName" >> $LogFile}
  685.                         {$LastAccessTime} {"`tDELETED FOLDER`t$($FolderList[$j].LastAccessTime.ToString('yyyy-MM-dd hh:mm:ss'))`t`t`t$TempName" >> $LogFile}
  686.                         Default {"`tDELETED FOLDER`t$($FolderList[$j].LastWriteTime.ToString('yyyy-MM-dd hh:mm:ss'))`t`t`t$TempName" >> $LogFile}
  687.                     }
  688.                 }
  689.                                 $script:FoldersNumber++
  690.                         }
  691.                 }
  692.         }
  693. }
  694. #endregion

  695. # Check if correct parameters are used
  696. if (-not $FolderPath) {Write-Warning 'Please specify the -FolderPath variable, this parameter is required. Use Get-Help .\deleteold.ps1 to display help.';exit}
  697. if (-not $FileAge) {Write-Warning 'Please specify the -FileAge variable, this parameter is required. Use Get-Help .\deleteold.ps1 to display help.';exit}
  698. if (-not $LogFile) {Write-Warning 'Please specify the -LogFile variable, this parameter is required. Use Get-Help .\deleteold.ps1 to display help.';exit}
  699. if ($Autolog) {F_Autolog}

  700. # Sets up the variables
  701. $Startdate = Get-Date
  702. $LastWrite = $Startdate.AddDays(-$FileAge)
  703. $StartTime = $Startdate.ToShortDateString()+", "+$Startdate.ToLongTimeString()
  704. $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"
  705.     # Populate the switches string with the switches and parameters that are set
  706.     if ($IncludePath) {
  707.             $Switches += "`r`n`t`t-IncludePath"
  708.             for ($j=0;$j -lt $IncludePath.Count;$j++) {$Switches+= "`r`n`t`t`t";$Switches+= $IncludePath[$j]}
  709.     }
  710.     if ($ExcludePath) {
  711.             $Switches += "`r`n`t`t-ExcludePath"
  712.             for ($j=0;$j -lt $ExcludePath.Count;$j++) {$Switches+= "`r`n`t`t`t";$Switches+= $ExcludePath[$j]}
  713.     }
  714.     if ($IncludeFileExtension) {
  715.             $Switches += "`r`n`t`t-IncludeFileExtension"
  716.             for ($j=0;$j -lt $IncludeFileExtension.Count;$j++) {$Switches+= "`r`n`t`t`t";$Switches+= $IncludeFileExtension[$j]}
  717.     }
  718.     if ($ExcludeFileExtension) {
  719.             $Switches += "`r`n`t`t-ExcludeFileExtension"
  720.             for ($j=0;$j -lt $ExcludeFileExtension.Count;$j++) {$Switches+= "`r`n`t`t`t";$Switches+= $ExcludeFileExtension[$j]}
  721.     }
  722.     if ($ExcludeDate) {
  723.             $Switches+= "`r`n`t`t-ExcludeDate"
  724.         $ExcludeDate | ConvertFrom-Csv -Header:'Item1','Item2','Item3' -ErrorAction SilentlyContinue | ForEach-Object {
  725.             $Switches += "`r`n`t`t`t"
  726.             $Switches += ($_.Item1,$_.Item2,$_.Item3 -join ',').Trim(',')
  727.         }            
  728.     }
  729.     if ($EmailTo) {
  730.             $Switches += "`r`n`t`t-EmailTo"
  731.             for ($j=0;$j -lt $EmailTo.Count;$j++) {$Switches+= "`r`n`t`t`t";$Switches+= $EmailTo[$j]}
  732.     }
  733.     if ($EmailFrom) {
  734.         $Switches += "`r`n`t`t-EmailFrom`r`n`t`t`t$EmailFrom"
  735.     }
  736.     if ($EmailSubject) {
  737.         $Switches += "`r`n`t`t-EmailSubject`r`n`t`t`t$EmailSubject"
  738.     }
  739.     if ($EmailSmtpServer) {
  740.         $Switches += "`r`n`t`t-EmailSmtpServer`r`n`t`t`t$EmailSmtpServer"
  741.     }
  742.     if ($ListOnly) {$Switches+="`r`n`t`t-ListOnly"}
  743.     if ($VerboseLog) {$Switches+="`r`n`t`t-VerboseLog"}
  744.     if ($Autolog) {$Switches+="`r`n`t`t-AutoLog"}
  745.     if ($Appendlog) {$Switches+="`r`n`t`t-AppendLog"}
  746.     if ($CreateTime) {$Switches+="`r`n`t`t-CreateTime"}
  747.     if ($LastAccessTime) {$Switches+="`r`n`t`t-LastAccessTime"}
  748.     if ($CleanFolders) {$Switches+="`r`n`t`t-CleanFolders"}
  749.     if ($NoFolder) {$Switches+="`r`n`t`t-NoFolder"}
  750.     if ($RegExPath) {$Switches+="`r`n`t`t-RegExPath"}
  751. [long]$FilesSize = 0
  752. [long]$FailedSize = 0
  753. [int]$FilesNumber = 0
  754. [int]$FilesFailed = 0
  755. [int]$FoldersNumber = 0
  756. [int]$FoldersFailed = 0

  757. # Sets up the email splat, displays a warning if not all variables have been correctly entered
  758. if ($EmailTo -or $EmailFrom -or $EmailSmtpServer) {
  759.     if (($EmailTo,$EmailFrom,$EmailSmtpServer) -contains '') {
  760.         Write-Warning 'EmailTo EmailFrom and EmailSmtpServer parameters only work if all three parameters are used, no email sent...'
  761.     } else {
  762.         $EmailSplat = @{
  763.             To = $EmailTo
  764.             From = $EmailFrom
  765.             SmtpServer = $EmailSmtpServer
  766.             Attachments = $LogFile
  767.         }
  768.         if ($EmailSubject) {
  769.             $EmailSplat.Subject = $EmailSubject
  770.         } else {
  771.             $EmailSplat.Subject = "deleteold.ps1 started at: $StartTime FolderPath: $FolderPath"
  772.         }
  773.     }
  774. }

  775. # Output text to console and write log header
  776. Write-Output ("-"*79)
  777. Write-Output "  Deleteold`t::`tScript to delete old files from folders"
  778. Write-Output ("-"*79)
  779. Write-Output "`n   Started  :   $StartTime`n   Folder   :`t$FolderPath`n   Switches :`t$Switches`n"
  780. if ($ListOnly){Write-Output "`t*** Running in Listonly mode, no files will be modified ***`n"}
  781. Write-Output ("-"*79)

  782. # If AppendLog switch is present log will be appended, not replaced
  783. if ($AppendLog) {
  784.     ("-"*79) >> $LogFile
  785. } else {
  786.     ("-"*79) > $LogFile
  787. }

  788. "  Deleteold`t::`tScript to delete old files from folders" >> $LogFile
  789. ("-"*79) >> $LogFile
  790. " " >> $LogFile
  791. "   Started  :   $StartTime" >> $LogFile
  792. " " >> $LogFile
  793. "   Folder   :   $FolderPath" >> $LogFile
  794. " " >> $LogFile
  795. "   Switches :   $Switches" >> $LogFile
  796. " " >> $LogFile
  797. ("-"*79) >> $LogFile
  798. " " >> $LogFile

  799. # Define the properties to be selected for the array, if createtime switch is specified
  800. # CreationTime is added to the list of properties, this is to conserve memory space
  801. $SelectProperty = @{'Property'='Fullname','Length','PSIsContainer'}
  802. if ($CreateTime) {
  803.         $SelectProperty.Property += 'CreationTime'
  804. } elseif ($LastAccessTime) {
  805.     $SelectProperty.Property += 'LastAccessTime'
  806. } else {
  807.         $SelectProperty.Property += 'LastWriteTime'
  808. }
  809. if ($ExcludeFileExtension -or $IncludeFileExtension) {
  810.     $SelectProperty.Property += 'Extension'
  811. }

  812. # Get the complete list of files and save to array
  813. Write-Output "`n   Retrieving list of files and folders from: $FolderPath"
  814. $CheckError = $Error.Count
  815. $FullArray = @(Get-ChildItem -LiteralPath $FolderPath -Recurse -ErrorAction SilentlyContinue -Force | Select-Object @SelectProperty)

  816. # Split the complete list of items into a separate list containing only the files
  817. $FileList = @($FullArray | Where-Object {$_.PSIsContainer -eq $false})
  818. $FolderList = @($FullArray | Where-Object {$_.PSIsContainer -eq $true})

  819. # If the IncludePath parameter is included then this loop will run. This will clear out any path not specified in the
  820. # include parameter. If the ExcludePath parameter is also specified
  821. if ($IncludePath) {
  822.     # If RegExpath has not been specified the script will escape all regular expressions from values specified
  823.     if (!$RegExPath) {
  824.         for ($j=0;$j -lt $IncludePath.Count;$j++) {
  825.                     [array]$NewFileList += @($FileList | Where-Object {$_.FullName -match [RegEx]::Escape($IncludePath[$j])})
  826.             [array]$NewFolderList += @($FolderList | Where-Object {$_.FullName -match [RegEx]::Escape($IncludePath[$j])})
  827.         }
  828.     } else {
  829.     # Process the list of files when RegExPath has been specified
  830.         for ($j=0;$j -lt $IncludePath.Count;$j++) {
  831.                     [array]$NewFileList += @($FileList | Where-Object {$_.FullName -match $IncludePath[$j]})
  832.             [array]$NewFolderList += @($FolderList | Where-Object {$_.FullName -match $IncludePath[$j]})
  833.         }        
  834.     }
  835.     $FileList = $NewFileList
  836.     $FolderList = $NewFolderList
  837.     $NewFileList=$NewFolderList = $null
  838. }

  839. # If the ExcludePath parameter is included then this loop will run. This will clear out the
  840. # excluded paths for both the filelist.
  841. if ($ExcludePath) {
  842.     # If RegExpath has not been specified the script will escape all regular expressions from values specified
  843.     if (!$RegExPath) {
  844.         for ($j=0;$j -lt $ExcludePath.Count;$j++) {
  845.             $FileList = @($FileList | Where-Object {$_.FullName -notmatch [RegEx]::Escape($ExcludePath[$j])})
  846.             $FolderList = @($FolderList | Where-Object {$_.FullName -notmatch [RegEx]::Escape($ExcludePath[$j])})
  847.             }
  848.     } else {
  849.     # Process the list of files when RegExPath has been specified
  850.         for ($j=0;$j -lt $ExcludePath.Count;$j++) {
  851.                     $FileList = @($FileList | Where-Object {$_.FullName -notmatch $ExcludePath[$j]})
  852.             $FolderList = @($FolderList | Where-Object {$_.FullName -notmatch $ExcludePath[$j]})
  853.             }
  854.     }
  855. }

  856. # If the -IncludeFileExtension is specified all filenames matching the criteria specified
  857. if ($IncludeFileExtension) {
  858.     for ($j=0;$j -lt $IncludeFileExtension.Count;$j++) {
  859.         # If no dot is present the dot will be added to the front of the string
  860.         if ($IncludeFileExtension[$j].Substring(0,1) -ne '.') {$IncludeFileExtension[$j] = ".$($IncludeFileExtension[$j])"}
  861.         [array]$NewFileList += @($FileList | Where-Object {$_.Extension -like $IncludeFileExtension[$j]})
  862.     }
  863.     $FileList = $NewFileList
  864.     $NewFileList=$null
  865. }

  866. # If the -ExcludeFileExtension is specified all filenames matching the criteria specified
  867. if ($ExcludeFileExtension) {
  868.     for ($j=0;$j -lt $ExcludeFileExtension.Count;$j++) {
  869.         # If no dot is present the dot will be added to the front of the string
  870.         if ($ExcludeFileExtension[$j].Substring(0,1) -ne '.') {$ExcludeFileExtension[$j] = ".$($ExcludeFileExtension[$j])"}
  871.         $FileList = @($FileList | Where-Object {$_.Extension -notlike $ExcludeFileExtension[$j]})
  872.     }
  873. }

  874. # Catches errors during read stage and writes to log, mostly catches permissions errors. Placed after Exclude/Include portion
  875. # of the script to ensure excluded paths are not generating errors.
  876. $CheckError = $Error.Count - $CheckError
  877. if ($CheckError -gt 0) {
  878.         for ($j=0;$j -lt $CheckError;$j++) {
  879.         # Verifies is the error does not match an excluded path, only errors not matching excluded paths will be written to the Log       
  880.         if ($ExcludePath) {
  881.             if ($(for ($k=0;$k -lt $ExcludePath.Count;$k++) {$Error[$j].TargetObject -match $ExcludePath[$k].SubString(0,$ExcludePath[$k].Length-2)}) -notcontains $true) {
  882.                 $TempErrorVar = "$($Error[$j].ToString()) ::: $($Error[$j].TargetObject)"
  883.                         "`tFAILED ACCESS`t$TempErrorVar" >> $LogFile
  884.             }
  885.             } else {
  886.             $TempErrorVar = "$($Error[$j].ToString()) ::: $($Error[$j].TargetObject)"
  887.                     "`tFAILED ACCESS`t$TempErrorVar" >> $LogFile
  888.         }
  889.     }
  890. }

  891. # Counter for prompt output
  892. $AllFileCount = $FileList.Count

  893. # If the -CreateTime switch has been used the script looks for file creation time rather than
  894. # file modified/lastwrite time
  895. if ($CreateTime) {
  896.         $FileList = @($FileList | Where-Object {$_.CreationTime -le $LastWrite})
  897. } elseif ($LastAccessTime) {
  898.     $FileList = @($FileList | Where-Object {$_.LastAccessTime -le $LastWrite})
  899. } else {
  900.     $FileList = @($FileList | Where-Object {$_.LastWriteTime -le $LastWrite})
  901. }

  902. # If the ExcludeDate parameter is specified the query is converted by the ConvertFrom-Query function. The
  903. # output of that table is a hashtable that is splatted to the ConvertTo-DateObject function which returns
  904. # an array of dates. All files that match a date in the returned array will be excluded from deletion which
  905. # allows for more specific exclusions.
  906. if ($ExcludeDate) {
  907.     $SplatDate = ConvertFrom-DateQuery $ExcludeDate
  908.     $ExcludedDates = @(ConvertTo-DateObject @SplatDate | Select-Object -Unique | Sort-Object -Descending)
  909.     if ($CreateTime) {
  910.         $FileList = @($FileList | Where-Object {$ExcludedDates -notcontains $_.CreationTime.Date})
  911.     } elseif ($LastAccessTime) {
  912.     $FileList = @($FileList | Where-Object {$_.LastAccessTime -le $LastWrite})
  913.     } else {
  914.         $FileList = @($FileList | Where-Object {$ExcludedDates -notcontains $_.LastWriteTime.Date})
  915.     }
  916.     [string]$DisplayExcludedDates = for ($j=0;$j -lt $ExcludedDates.Count;$j++) {
  917.         if ($j -eq 0) {
  918.             "`n   ExcludedDates: $($ExcludedDates[$j].ToString('yyyy-MM-dd'))"
  919.         } else {
  920.             $ExcludedDates[$j].ToString('yyyy-MM-dd')
  921.         }
  922.         # After every fifth date start on the next line
  923.         if ((($j+1) % 6) -eq 0) {"`n`t`t "}
  924.     }
  925.     $DisplayExcludedDates
  926. }

  927. # Defines the list of folders, either a complete list of all folders if -CleanFolders
  928. # was specified or just the folders containing old files. The -NoFolder switch will ensure
  929. # the folder structure is not modified and only files are deleted.
  930. if ($CleanFolders) {
  931.     # Uses the FolderList variable defined at the start of the script, including any exclusions/inclusions
  932. } elseif ($NoFolder) {
  933.     $FolderList = @()
  934. } else {
  935.     $FolderList = @($FileList | ForEach-Object {
  936.         Split-Path -Path $_.FullName} |
  937.         Select-Object -Unique | ForEach-Object {
  938.             Get-Item -LiteralPath $_ -ErrorAction SilentlyContinue | Select-Object @SelectProperty})
  939. }

  940. # Clear original array containing files and folders and create array with list of older files
  941. $FullArray = ""

  942. # Write totals to console
  943. Write-Output         "`n   Files`t: $AllFileCount`n   Folders`t: $($FolderList.Count) `n   Old files`t: $($FileList.Count)"

  944. # Execute main functions of script
  945. if (-not $ListOnly) {
  946.     Write-Output "`n   Starting with removal of old files..."
  947. } else {
  948.     Write-Output "`n   Listing files..."
  949. }
  950. F_Deleteoldfiles
  951. if (-not $ListOnly) {
  952.     Write-Output "   Finished deleting files`n"
  953. } else {
  954.     Write-Output "   Finished listing files`n"
  955. }
  956. if (-not $ListOnly) {
  957.         Write-Output "   Check/remove empty folders started..."
  958.         F_Checkforemptyfolder
  959.         Write-Output "   Empty folders deleted`n"
  960. }

  961. # Pre-format values for footer
  962. $TimeTaken = ((Get-Date) - $StartDate).ToString().SubString(0,8)
  963. $FilesSize = $FilesSize/1MB
  964. [string]$FilesSize = $FilesSize.ToString()
  965. $FailedSize = $FailedSize/1MB
  966. [string]$FailedSize = $FailedSize.ToString()
  967. $EndDate = "$((Get-Date).ToShortDateString()), $((Get-Date).ToLongTimeString())"

  968. # Write footer to log and output to console
  969. Write-Output ($Footer = @"

  970. $("-"*79)

  971.    Files               : $FilesNumber
  972.    Filesize(MB)        : $FilesSize
  973.    Files Failed        : $FilesFailed
  974.    Failedfile Size(MB) : $FailedSize
  975.    Folders             : $FoldersNumber
  976.    Folders Failed      : $FoldersFailed

  977.    Finished Time       : $EndDate
  978.    Total Time          : $TimeTaken

  979. $("-"*79)
  980. "@)

  981. Out-File -FilePath $LogFile -Append -InputObject $Footer

  982. # Section of script that emails the logfile if required parameters are specified.
  983. if ($EmailSplat) {
  984.     Send-MailMessage @EmailSplat
  985. }

  986. # Clean up variables at end of script
  987. $FileList=$FolderList = $null
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|批处理之家 ( 渝ICP备10000708号 )

GMT+8, 2026-3-17 05:15 , Processed in 0.022837 second(s), 8 queries , File On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表