简体   繁体   中英

Delete all file and keep the latest using powershell

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.

    • Passing script block { $_.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.
    • Eg, the result for both '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, with
    Sort-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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM