Reputation: 63
I'm having an issue with a software generating many files. I can't control the generation of files, but I can handle them after. Files have this kind of name:
"RandomString".*ProjectNumber*.*Date*.*Time*.txt
For example:
1297729137.0004202.20180925.232147.txt
I want to keep for the same ProjectNumber, only the last generated TXT file.
Any idea how I can do that easily?
Upvotes: 0
Views: 244
Reputation: 23355
I think this should meet your needs:
$Files = Get-ChildItem *.txt
$ProjectFiles = $Files | ForEach-Object {
$FileName = $_.Name -Split '\.'
[pscustomobject]@{
Name = $_.Fullname
RandomString = $FileName[0]
ProjectNumber = $FileName[1]
DateTime = [datetime]::parseexact($FileName[2] + $FileName[3], 'yyyyMMddHHmmss', $null)
}
}
$FilesToRemove = ($ProjectFiles | Group-Object 'ProjectNumber') | ForEach-Object {
($_.Group | Sort-Object DateTime -Descending | Select-Object -Skip 1).Name
} | Where-Object { $_ -ne $null }
$FilesToRemove | Remove-Item -WhatIf
This retrieves all the text files and then creates a new custom PowerShell object with the name of the file and the properties you've specified from the filename by splitting on the '.'. We convert the date and time strings into a datetime
object by using the parseexact
method.
We can then use this new object to group the files by the project number, and then go through each of those groups sorting the results by Date, skipping the first result (which should be the newest dated project file) and returning the name of all others.
Then we can remove those file names with Remove-Item
. When you're happy it's doing what you expect, remove the -WhatIf
.
Note that this code assumes:
Upvotes: 2
Reputation: 67216
@echo off
setlocal EnableDelayedExpansion
rem Search files, keep the last one by project
for /F "tokens=1-4 delims=." %%a in ('dir /B *.txt') do (
if "%%c%%d" gtr "!project[%%b]!" set "project[%%b]=%%c%%d"
)
rem Remove the rest of files
for /F "tokens=1-4 delims=." %%a in ('dir /B *.txt') do (
if "%%c%%d" neq "!project[%%b]!" del "%%a.%%b.%%c.%%d.txt"
)
This method assume that just such a files exist in the folder; if not, just change the wild-card by *.*.*.*.txt
Upvotes: 3
Reputation:
A similar approach to Mark Wragg, but using
Where-Object
with a match and capture groups to separate the file name elements.Select-Object
to append calculated porperties PN and DT for ProjectName and DateTime-WhatIf
option to just show what would be deleted.Get-ChildItem *.txt | Where-Object Name -match '^(([^\.]+)\.){4}txt$' |
Select-Object *,@{n='PN';e={$Matches[2]}},@{n='DT';e={$Matches[3]+$Matches[4]}} |
Group-Object PN |
ForEach-Object{ $_.Group | sort DT -desc | select -skip 1 | RM -Whatif }
Upvotes: 1