Reputation: 3524
I want to keep 5 last generated file in my directory, retaining only the first file of each date, because inside my subfolders, I have generated files multiple times in the same day.
I have multiple folder with subfolder named "old"
C:\test\folder1\old
C:\test\toto\old
...
So for example in my subfolder I have this :
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 07/06/2013 12:01 231248950 geofi.ry.7.0.0.159940.zip
-a--- 07/06/2013 12:33 231248506 geofi.ry.7.0.0.159950.zip
-a--- 07/06/2013 14:51 231248957 geofi.ry.7.0.0.159962.zip
-a--- 17/06/2013 19:47 231248860 geofi.ry.7.0.0.160871.zip
-a--- 18/06/2013 11:03 231248480 geofi.ry.7.0.0.160907.zip
-a--- 23/06/2013 07:30 231250266 geofi.ry.7.0.0.161571.zip
-a--- 23/06/2013 21:30 231250266 geofi.ry.7.0.0.161563.zip
-a--- 04/07/2013 00:42 231249910 geofi.ry.7.0.0.162695.zip
-a--- 04/07/2013 16:12 231249910 geofi.ry.7.0.0.162647.zip
-a--- 08/07/2013 16:10 231250481 geofi.ry.7.0.0.163046.zip
-a--- 10/07/2013 08:40 231250476 geofi.ry.7.0.0.163378.zip
-a--- 17/07/2013 10:22 231249418 geofi.ry.7.0.0.164001.zip
I want to keep theses files :
-a--- 17/07/2013 10:22 231249418 geofi.ry.7.0.0.164001.zip
-a--- 10/07/2013 08:40 231250476 geofi.ry.7.0.0.163378.zip
-a--- 08/07/2013 16:10 231250481 geofi.ry.7.0.0.163046.zip
-a--- 04/07/2013 00:42 231249910 geofi.ry.7.0.0.162695.zip (on this date i have two files, I want to keep the first generated at this date 00:42).
-a--- 23/06/2013 07:30 231250266 geofi.ry.7.0.0.161571.zip (on this date i have two files, I want to keep the first generated at this date 07:30).
This is a draft but I'm stuck, how can I compare time?
$Days = "5"
$TargetFolder = "C:\test\"
$Extension = "*.zip"
$Files = Get-Childitem $TargetFolder -Include $Extension -Recurse | sort-object {$_.LastWriteTime} -Descending | ? { $_.fullname -match "old" } | select-object -First 1
$most_recent_date = $files.LastWriteTime
$LastWrite = $most_recent_date.Add(-$Days)
$Files2 = Get-Childitem $TargetFolder -Include $Extension -Recurse | Where {$_.LastWriteTime -le "$LastWrite"} | ? { $_.fullname -match "old" }
foreach ($File in $Files2)
{
if ($File -ne $NULL)
{
Remove-Item $File.FullName | out-null
}
else
{
Write-Host "No more files to delete!"
}
}
Thanks
Upvotes: 4
Views: 1071
Reputation: 37569
The job can also be done with the help of good old batch with it's built-in associative arrays:
@ECHO OFF &SETLOCAL ENABLEDELAYEDEXPANSION
FOR /f "delims=" %%a IN ('dir /a-d /b *.zip') DO (
FOR /f "tokens=2-4delims=/ " %%b IN ("%%a") DO SET "filedate=%%d%%c%%b"
FOR /f "tokens=3" %%b IN ("%%a") DO SET "filetime=%%b"
SET "$!filedate!$!filetime!=%%a"
)
FOR /f "delims=$" %%a IN ('set "$"') DO (
IF NOT "%%a"=="!files!" (
SET "file="
FOR /f "tokens=2*delims=$=" %%b IN ('set "$%%a"') DO IF NOT DEFINED file SET "file=%%c"
SET "#%%a=!file!"
SET "files=%%a"
SET /a filecount+=1
)
)
SET /a filecount-=5
FOR /f "skip=%filecount%tokens=2delims==" %%a IN ('set "#"') DO ECHO %%a
Session protocol:
>dir /a-d *.zip -a--- 07/06/2013 12:01 231248950 geofi.ry.7.0.0.159940.zip -a--- 07/06/2013 12:33 231248506 geofi.ry.7.0.0.159950.zip -a--- 07/06/2013 14:51 231248957 geofi.ry.7.0.0.159962.zip -a--- 17/06/2013 19:47 231248860 geofi.ry.7.0.0.160871.zip -a--- 18/06/2013 11:03 231248480 geofi.ry.7.0.0.160907.zip -a--- 23/06/2013 07:30 231250266 geofi.ry.7.0.0.161571.zip -a--- 23/06/2013 21:30 231250266 geofi.ry.7.0.0.161563.zip -a--- 04/07/2013 00:42 231249910 geofi.ry.7.0.0.162695.zip -a--- 04/07/2013 16:12 231249910 geofi.ry.7.0.0.162647.zip -a--- 08/07/2013 16:10 231250481 geofi.ry.7.0.0.163046.zip -a--- 10/07/2013 08:40 231250476 geofi.ry.7.0.0.163378.zip -a--- 17/07/2013 10:22 231249418 geofi.ry.7.0.0.164001.zip >script.bat -a--- 23/06/2013 07:30 231250266 geofi.ry.7.0.0.161571.zip -a--- 04/07/2013 00:42 231249910 geofi.ry.7.0.0.162695.zip -a--- 08/07/2013 16:10 231250481 geofi.ry.7.0.0.163046.zip -a--- 10/07/2013 08:40 231250476 geofi.ry.7.0.0.163378.zip -a--- 17/07/2013 10:22 231249418 geofi.ry.7.0.0.164001.zip
Upvotes: 3
Reputation: 200233
If you want to keep the most recent file of the 5 most recent dates across all folders try this:
$TargetFolder = 'C:\test'
$Extension = '*.zip'
$files = gci $TargetFolder -Include $Extension -Recurse |
? { -not $_.PSIsContainer -and $_.Directory.Name -eq 'old' }
$keep = $files | sort LastWriteTime -Desc | group {$_.LastWriteTime.Date} |
% {$_.Group[-1].FullName} | select -First 5
$totalSize = ($files | ? { $keep -notcontains $_.FullName } |
Measure-Object -Sum Length).Sum
$files | ? { $keep -notcontains $_.FullName } | Remove-Item -WhatIf
"Deleted size: {0:N3}" -f ($totalSize / 1GB)
If you want to keep the most recent file of the 5 most recent dates from each folder try this:
$TargetFolder = 'C:\test'
$Extension = '.zip'
$totalSize = 0
gci $TargetFolder -Recurse | ? { $_.PSIsContainer -and $_.Name -eq 'old' } | % {
$files = gci $_.FullName | ? { -not $_.PSIsContainer -and
$_.Extension -eq $Extension }
$keep = $files | sort LastWriteTime -Desc | group {$_.LastWriteTime.Date} |
% {$_.Group[-1].FullName} | select -First 5
$totalSize += ($files | ? { $keep -notcontains $_.FullName } |
Measure-Object -Sum Length).Sum
$files | ? { $keep -notcontains $_.FullName } | Remove-Item -WhatIf
}
"Deleted size: {0:N3}" -f ($totalSize / 1GB)
Remove the -WhatIf
-switch from Remove-Item
and re-run the code after you double-checked that the code really does what you want.
Upvotes: 2
Reputation: 72610
What about this one line ?
Get-Childitem $TargetFolder -Include $Extension -Recurse |Sort-Object lastwritetime -Descending | Group-Object @{Expression={($_.lastwritetime).Date}} | % {$_.group | Select-Object -Last 1}
1) Get all the files, here you can add the filters you want.
2) Sort the result descending on the lastwritetime.
3) Group the result by date, so I get a group for each date.
4) Get the last element in the goup for each date.
I forgot | Select-Object -First 5
Get-Childitem $TargetFolder -Include $Extension -Recurse |Sort-Object lastwritetime -Descending | Group-Object @{Expression={($_.lastwritetime).Date}} | % {$_.group | Select-Object -Last 1} | Select-Object -First 5
This is working only for one dir try this :
Get-ChildItem $TargetFolder -Recurse | where {$_.psiscontainer} | % { Get-ChildItem -Path $_.fullname -filter $Extension |Sort-Object lastwritetime -Descending | Group-Object @{Expression={($_.lastwritetime).Date}} | % {$_.group | Select-Object -Last 1} | Select-Object -First 5}
Upvotes: 1
Reputation: 11188
I assume from your question that you only want to keep 5 files across all sub folders, if so the code below will do what you want. If you want to keep 5 files per sub folder then you will to create an outer loop of those folders first and then run the code below for each individual folder.
$TargetFolder = "C:\test\"
$AllFiles = Get-Childitem $TargetFolder -Filter *.zip -Recurse |
? { $_.fullname -match "old" -and -not $_.PSIsContainer }
$KeepFiles = $AllFiles |
Sort-Object LastWriteTime |
Group-Object {$_.LastWriteTime.Date} |
% {$_.Group[0]} |
Sort-Object LastWriteTime -Descending |
Select-Object -First 5
Compare-Object -ReferenceObject $AllFiles -DifferenceObject $KeepFiles -PassThru |
Remove-Item
Upvotes: 1