I have a file that i backup daily, as sample like this :
Before deleting all but the latest :
Folder C:\Backup\
File :
Backup1-Database-A.bak | 1/10/2020 1:24 PM
Backup2-Database-A.bak | 2/10/2020 1:24 PM
Backup1-Database-B.bak | 1/10/2020 1:24 PM
Backup2-Database-B.bak | 2/10/2020 1:24 PM
Backup2-Database-B.bak | 3/10/2020 1:24 PM
Desired state after deleting all but the latest :
Folder C:\Backup\
File :
Backup2-Database-A.bak | 2/10/2020 1:24 PM
Backup2-Database-B.bak | 3/10/2020 1:24 PM
How can I keep the latest file for each database?
I'm using this script, but it deletes all .bak
so the backup of database A is gone, but I want to keep the latest for each database.
$mydays = (Get-Date).AddDays(-7)
$path = "C:\Backup\"
Get-Childitem -path $path -recurse -force | Where-Object { !$_.PSIsContainer -and $_.name -like "*.bak" -and $_.LastWriteTime -lt $mydays} | Remove-Item -Force
As Lee_Daily suggests, rather than using a time window to filter by, it is simpler to sort your files by last write time and delete all but the latest files.
The challenge is to determine which files relate to the same database and should therefore be considered as a group , so that you keep the most recent backup in each group .
The code below uses the following approach:
The Group-Object
cmdlet allows you to group the input files by the shared part of the file names that indicates the database.
{ $_.Name -replace '^Backup\\d+-' }
to Group-Object
uses the regex-based -replace
operator to make it group the input file objects by the shared name part that indicates the source database, by removing the 'Backup<n>-'
prefix.'Backup1-Database-A.bak'
and 'Backup2-Database-A.bak'
is just 'Database-A.bak'
, so the two files are grouped together. The files in each resulting group can then be sorted by last write time in descending order, withSort-Object
.
You can exclude the first - and therefore most recent - file from the output with Select-Object
-Skip 1
.
The resulting files - all but the most recent ones for each database - can then be sent to Remove-Item
.
$path = 'C:\Backup'
Get-Childitem -Path $path -Recurse -Force -File -Filter *.bak |
Group-Object { $_.Name -replace '^Backup\d+-' } |
ForEach-Object {
$_.Group | Sort-Object LastWriteTime -Descending | Select-Object -Skip 1 |
Remove-Item -Force -Whatif
}
Note: The -WhatIf
common parameter in the command above previews the operation. Remove -WhatIf
once you're sure the operation will do what you want.
Also note the simplification of the initial file selection: -File
(PSv3+) limits output to files only (not also directories), and -Filter *.bak
is an efficient way to filter by filename extension.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.