0
votes

I have a folder that contains a lot of files, multiple files per day.

I would like to script something that deletes all but the latest file per day.

I have seen a lot of scripts that delete files over X days old but this is slightly different and having written no powershell before yesterday (I'm exclusively tsql), I'm not really sure how to go about it.

I'm not asking anyone to write the code for me but maybe describe the methods of achieving this would be good and I can go off an research how to put it into practise.

All files are in a single directory, no subfolders. there are files I dont want to delete, the files i want to delete have file name in format constant_filename_prefix_YYYYMMDDHHMMSS.zip

Is powershell the right tool? Should i instead be looking at Python (which I also don't know) Powershell is more convinient since other code we have is written in PS.

1
what have you tried? what did not work as expected? this site is mostly focused on helping with existing code ... [grin]Lee_Dailey
Its kind of a "I dont even know where to start" situationJames Lester
ah! well, it looks like Theo has provided you with some code that otta work ... [grin]Lee_Dailey
We haven't heard from you.. Did my answer solve your problem? If so, please consider accepting it by clicking ✓ on the left. This will help others with a similar question finding it more easily.Theo

1 Answers

0
votes

PowerShell has easy to use cmdlets for this kind of thing.

The question to me is if you want the use the dates in the file names, or the actual LastWriteTime dates of the files themselves (as shown in File Explorer).

Below two ways of handling this. I've put in a lot of code comments to help you get the picture.

If you want to remove the files based on their actual last write times:

$sourceFolder = 'D:\test'                                             # put the path to the folder where your files are here
$filePrefix   = 'constant_filename_prefix'

Get-ChildItem -Path $sourceFolder -Filter "$filePrefix*.zip" -File |  # get files that start with the prefix and have the extension '.zip'
    Where-Object { $_.BaseName -match '_\d{14}$' } |                  # that end with an underscore followed by 14 digits
    Sort-Object -Property LastWriteTime -Descending |                 # sort on the LastWriteTime property
    Select-Object -Skip 1 |                                           # select them all except for the first (most recent) one
    Remove-Item -Force -WhatIf                                        # delete these files

OR

If you want to remove the files based the dates in the file names.
Because the date formats you used are sortable, you can safely sort on the last 14 digits of the file BaseName:

$sourceFolder = 'D:\test' 
$filePrefix   = 'constant_filename_prefix'

Get-ChildItem -Path $sourceFolder -Filter "$filePrefix*.zip" -File |                 # get files that start with the prefix and have the extension '.zip'
    Where-Object { $_.BaseName -match '_\d{14}$' } |                                 # that end with an underscore followed by 14 digits
    Sort-Object -Property @{Expression = {$_.BaseName.Substring(14)}} -Descending |  # sort on the last 14 digits descending
    Select-Object -Skip 1 |                                                          # select them all except for the first (most recent) one
    Remove-Item -Force -WhatIf                                                       # delete these files

In both alternatives you will find there is a switch -WhatIf at the end of the Remove-Item cmdlet. Yhis is for testing the code and no files wil actually be deleted. Instead, with this switch, in the console it writes out what would happen.

Once you are satisfied with this output, you can remove or comment out the -WhatIf switch to have the code delete the files.


Update

As I now understand, there are multiple files for several days in that folder and you want to keep the newest file for each day, deleting the others.

In that case, we have to create 'day' groups of the files and withing every group sort by date and delete the old files.
This is where the Group-Object comes in.

Method 1) using the LastWriteTime property of the files

$sourceFolder = 'D:\test'                                               # put the path to the folder where your files are here
$filePrefix   = 'constant_filename_prefix'

Get-ChildItem -Path $sourceFolder -Filter "$filePrefix*.zip" -File |    # get files that start with the prefix and have the extension '.zip'
    Where-Object { $_.BaseName -match '_\d{14}$' } |                    # that end with an underscore followed by 14 digits
    Group-Object -Property @{Expression = { $_.LastWriteTime.Date }} |  # create groups based on the date part without time part
        ForEach-Object {
            $_.Group | 
            Sort-Object -Property LastWriteTime -Descending |           # sort on the LastWriteTime property
            Select-Object -Skip 1 |                                     # select them all except for the first (most recent) one
            Remove-Item -Force -WhatIf                                  # delete these files
        }

Method 2) using the date taken from the file names:

$sourceFolder = 'D:\test'                                                                    # put the path to the folder where your files are here
$filePrefix   = 'constant_filename_prefix'

Get-ChildItem -Path $sourceFolder -Filter "$filePrefix*.zip" -File |                         # get files that start with the prefix and have the extension '.zip'
    Where-Object { $_.BaseName -match '_\d{14}$' } |                                         # that end with an underscore followed by 14 digits
    Group-Object -Property @{Expression = { ($_.BaseName -split '_')[-1].Substring(0,8)}} |  # create groups based on the date part without time part
        ForEach-Object {
            $_.Group | 
            Sort-Object -Property @{Expression = {$_.BaseName.Substring(14)}} -Descending |  # sort on the last 14 digits descending
            Select-Object -Skip 1 |                                                          # select them all except for the first (most recent) one
            Remove-Item -Force -WhatIf                                                       # delete these files
        }