Sometimes it is required to delete files older than a date or older by age. Powershell is excelent tool to perform this. Below is a simple script to delete files by age:
$folderName= 'C:\folderToCheckContents' #add the folder as variable on top in order for easier modifications
$files = Get-ChildItem -Path $folderName -Recurse -File #file is used to get only the files and exclude the folders
#$cutoffDate = (Get-Date) - [timespan]"90" #90 days
$cutoffDate = (Get-Date) - [timespan]"0:30" #30 minutes for testing
foreach ($singleFile in $files) {
if ($singleFile.LastWriteTime -le $cutoffDate) {
# Remove-Item $singleFile.FullName #uncomment the delete befor real deletion start. the full path of the file is required, #because it might not get the correct path
$singleFile.FullName >> ($folderName +"_deleted.txt") #write log of what was deleted
}
}
despite the comments in the script, some details might need additional clarification.
It is advisable to add the starting folder as variable for easier modification. As best practice, the first rows are with useful comments and the variables that are used for input. Of course this can be done with parameter, but hardcoding it at easiliy modifiable place is also common.
The GCI gets files and folders in the current folder by default, so Recurse switch is enabled in order to get also the contents of the subfolders and Files is used to get only the files in the buffer. Combining them searches in the subfolders, but does not get the subfolders in the list.
If Files switch is not used, then the script by default warns for non empty folders and the actions have to be confirmed. -Recurse -Confirm:$false can be used but more contents might be silently deleted.
For the date a [TimeSpan] as variable type is used, so PowerShell automatically converts the string do date and date operations can be performed.
Other easy options to add date are for example enter the cutoff date directly like
Get-Date -Date "2024-06-20T21:54:32"
[DateTime]"Jun-20-2024 11:15 pm"
[DateTime]"Jun-20-2024 21:15"
[DateTime]"Jun-20";
[DateTime]"06-20";
Afterwards the forEach loop checks each file and compares the file time with the predefined time. There are several times available for the files- CreationTime, LastWriteTime and LastAccessTime. They are also available in UTC format without need to recalculate it.
Remove-Item requires the full name if written as above. $singleFile does not work, but piping the variable and then removing the file actually works
$singleFile | Remove-Item
Afterwards is writing the file name to a log file. In the above code the alias is used (same as used in the CMD scipts), but also
$singleFile.FullName | Out-File ($folderName +"_deleted.txt") -Append
can be used instead. If the file property FullName is not specified, the default outut will be used, which will contain additional information.
If the folders have to be removed by creation time, then it gets a little tricky, because a folder contents can be changed, but the contents removed, which results in update of the LastAccessTime and LastWriteTime, but if folder was created a year ago and contents get rotated, then falso positive results might be expected for CreationTime. If the process/user that is creating the files has sufficient permissions (and checks in advance) the folders might get recreated.
Because creating the test environment is as a rule done right before the tests, old files are not always present and after the tests they get consumed (deleted or updated). It is possible to use PowerShell to set the creation date to a chosen date by assigning older date to the files/folders.
$newCreationTime = Get-Date -Date "2024-06-20T21:54:32"
$item2mofidy = get-item -path "some_path"
$item2mofidy.CreationTime = $newCreationTime
$item2mofidy.LastWriteTime = $newCreationTime
This works for both (folders and files), with folders more frequently locked by some process.
If the files are neatly organized in folders with timestamp as name, then also checking the name and comparing to the predefined date can be used, also with incomplete string. Sometimes it might be advisable (just to be on the safe side) to use minimum date and maximum date when comparing with the name, like following.
'202010' -gt '20200131234' #results true
'202010' -gt '20201131234' #results false
'3' -gt '20201131234' #results true
'1a' -gt '20201131234' #results false
'2a' -gt '20201131234' #results true
But folder named “203” (totally unrelated with the timestamps) or some small number can be also affected, if other process/user also writes data there.