227

I would like to delete only the files that were created more than 15 days ago in a particular folder. How could I do this using PowerShell?

Ewen Cartwright
  • 15,378
  • 4
  • 22
  • 21
user2470170
  • 2,320
  • 2
  • 13
  • 8
  • 11
    Most of the answers use CreationTime however it gets reset when a file is copied so you may not get the results you want. LastWriteTime is what corresponds to the "Date Modified" in Windows Explorer. – Roland Schaer Sep 29 '16 at 14:22
  • I don't think this is worth of an answer in itself but I think it's worth mentioning that using robocopy to delete empty directories is considerably faster than `Remove-Item`. For example: `robocopy "$($Directory)" "$($Directory)" /S /move /W:5`. The [`/s`](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/robocopy) param copies files but not empty directories. In my tests, I have 3m files in 1.4m folders and the entire job takes 16 minutes in robocopy but 43 minutes using Remove-Item. – Dan Atkinson Aug 23 '23 at 20:46

11 Answers11

380

The given answers will only delete files (which admittedly is what is in the title of this post), but here's some code that will first delete all of the files older than 15 days, and then recursively delete any empty directories that may have been left behind. My code also uses the -Force option to delete hidden and read-only files as well. Also, I chose to not use aliases as the OP is new to PowerShell and may not understand what gci, ?, %, etc. are.

$limit = (Get-Date).AddDays(-15)
$path = "C:\Some\Path"

# Delete files older than the $limit.
Get-ChildItem -Path $path -Recurse -Force | Where-Object { !$_.PSIsContainer -and $_.CreationTime -lt $limit } | Remove-Item -Force

# Delete any empty directories left behind after deleting the old files.
Get-ChildItem -Path $path -Recurse -Force | Where-Object { $_.PSIsContainer -and (Get-ChildItem -Path $_.FullName -Recurse -Force | Where-Object { !$_.PSIsContainer }) -eq $null } | Remove-Item -Force -Recurse

And of course if you want to see what files/folders will be deleted before actually deleting them, you can just add the -WhatIf switch to the Remove-Item cmdlet call at the end of both lines.

If you only want to delete files that haven't been updated in 15 days, vs. created 15 days ago, then you can use $_.LastWriteTime instead of $_.CreationTime.

The code shown here is PowerShell v2.0 compatible, but I also show this code and the faster PowerShell v3.0 code as handy reusable functions on my blog.

deadlydog
  • 22,611
  • 14
  • 112
  • 118
  • 36
    Thank you for not using alias's. For someone who is new to powershell and found this post through a Google search, I consider your answer to be the best. – Geoff Dawdy Oct 22 '13 at 21:11
  • 1
    I tried @deadlydog's suggestion and no matter if I specify -15 or -35 with varying file creation dates going back months (or recent), it's deleting the entire contents of the directory. – Michele Feb 14 '14 at 14:44
  • 6
    If files may be in use it's also worth adding " -ErrorAction SilentlyContinue" to the RemoveItem command. – Kevin Owen Jul 30 '15 at 10:21
  • 22
    Thanks! I use $_.LastwriteTime instead of $_.CreationTime – Lauri Lubi Dec 03 '15 at 10:31
  • 1
    @Michele I appreciate this is about 2 years late, however, I just ran into the same problem and found it to be typing error. I somehow typed $CreationTime rather than $_.CreationTime. Everything ran fine, it just deletes everything! :) I found it hard to spot. Maybe that'll help someone else. – Kinetic Apr 27 '16 at 08:48
  • I'm trying out this script because forfiles doesn't support UNC paths. However your script doesn't work either because it cuts off the end of my path for some reason. \\SERVERNAME\Downloads$\%username%\Downloads\ – Nathan McKaskle Jul 26 '16 at 17:33
  • 2
    The second command in that script always gets an error that Get-ChildItem cannot find part of the path. It gets a directory not found exception. Yet it deletes the empty folders without a problem. Not sure why it's getting an error despite working. – Nathan McKaskle Aug 22 '16 at 18:12
  • @LauriLubi thank you, your suggestion worked for me whereas CreationTime did not. – Fieldfare Jun 17 '21 at 09:38
87

just simply (PowerShell V5)

Get-ChildItem "C:\temp" -Recurse -File | Where CreationTime -lt  (Get-Date).AddDays(-15)  | Remove-Item -Force
Esperento57
  • 16,521
  • 3
  • 39
  • 45
19

Another way is to subtract 15 days from the current date and compare CreationTime against that value:

$root  = 'C:\root\folder'
$limit = (Get-Date).AddDays(-15)

Get-ChildItem $root -Recurse | ? {
  -not $_.PSIsContainer -and $_.CreationTime -lt $limit
} | Remove-Item
Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328
17

Basically, you iterate over files under the given path, subtract the CreationTime of each file found from the current time, and compare against the Days property of the result. The -WhatIf switch will tell you what will happen without actually deleting the files (which files will be deleted), remove the switch to actually delete the files:

$old = 15
$now = Get-Date

Get-ChildItem $path -Recurse |
Where-Object {-not $_.PSIsContainer -and $now.Subtract($_.CreationTime).Days -gt $old } |
Remove-Item -WhatIf
StackzOfZtuff
  • 2,534
  • 1
  • 28
  • 25
Shay Levy
  • 121,444
  • 32
  • 184
  • 206
10

Try this:

dir C:\PURGE -recurse | 
where { ((get-date)-$_.creationTime).days -gt 15 } | 
remove-item -force
Roland Jansen
  • 2,733
  • 1
  • 16
  • 21
  • I believe the last `-recurse` is one too much, no? The dir listing is recursively, the deletion of the item should not be with childs included, right? – Joost Jul 31 '13 at 00:00
  • If the directory you're working with is two directories deep a second -recurse is needed. – Bryan S. Nov 20 '15 at 18:45
8

Esperento57's script doesn't work in older PowerShell versions. This example does:

Get-ChildItem -Path "C:\temp" -Recurse -force -ErrorAction SilentlyContinue | where {($_.LastwriteTime -lt  (Get-Date).AddDays(-15) ) -and (! $_.PSIsContainer)} | select name| Remove-Item -Verbose -Force -Recurse -ErrorAction SilentlyContinue
KERR
  • 1,312
  • 18
  • 13
6

If you are having problems with the above examples on a Windows 10 box, try replacing .CreationTime with .LastwriteTime. This worked for me.

dir C:\locationOfFiles -ErrorAction SilentlyContinue | Where { ((Get-Date)-$_.LastWriteTime).days -gt 15 } | Remove-Item -Force
Jeff Blumenthal
  • 442
  • 6
  • 8
4

Another alternative (15. gets typed to [timespan] automatically):

ls -file | where { (get-date) - $_.creationtime -gt 15. } | Remove-Item -Verbose
js2010
  • 23,033
  • 6
  • 64
  • 66
2
#----- Define parameters -----#
#----- Get current date ----#
$Now = Get-Date
$Days = "15" #----- define amount of days ----#
$Targetfolder = "C:\Logs" #----- define folder where files are located ----#
$Extension = "*.log" #----- define extension ----#
$Lastwrite = $Now.AddDays(-$Days)

#----- Get files based on lastwrite filter and specified folder ---#
$Files = Get-Childitem $Targetfolder -include $Extension -Recurse | where {$_.LastwriteTime -le "$Lastwrite"}

foreach ($File in $Files)
{
    if ($File -ne $Null)
    {
        write-host "Deleting File $File" backgroundcolor "DarkRed"
        Remove-item $File.Fullname | out-null
    }
    else {
        write-host "No more files to delete" -forgroundcolor "Green"
    }
}
Daniell
  • 3
  • 2
Ikruzzz
  • 228
  • 1
  • 4
  • 15
  • Also, it will never reach the *else* statement, because if `$Files` is empty it won't enter the *foreach* statement. You should place the foreach in the *if* statement. – Dieter May 26 '15 at 08:16
  • @mati actually it can reach the else statement. We have a similar for loop based on a file list and it regularly enters the for loop with the $File variable as null – BeowulfNode42 Jun 29 '15 at 08:53
  • I'm guessing so- just stumbed across the same script here; http://www.networknet.nl/apps/wp/published/powershell-delete-files-older-than-x-days – Shawson Apr 04 '16 at 09:12
1
$limit = (Get-Date).AddDays(-15)
$path = "C:\Some\Path"

# Delete files older than the $limit.
Get-ChildItem -Path $path -Force | Where-Object { !$_.PSIsContainer -and $_.CreationTime -lt $limit } | Remove-Item -Force -Recurse

This will delete old folders and it content.

Aigar
  • 11
  • 1
0

The following code will delete files older than 15 days in a folder.

$Path = 'C:\Temp'
$Daysback = "-15"
$CurrentDate = Get-Date
$DatetoDelete = $CurrentDate.AddDays($Daysback)
Get-ChildItem $Path -Recurse  | Where-Object { $_.LastWriteTime -lt $DatetoDelete } | Remove-Item
  • This solution has been posted so many times already. Why are you posting it again? (without at least explaining why you believed your solution is different/better) – Martin Prikryl Aug 26 '22 at 08:41
  • 1
    Hi. I tested solutions above but they cannot solve the problem in the question. My answer is correct and I want help community for solving the problem. – Karabakh Azerbaijan Sep 01 '22 at 10:57
  • What's wrong for example with [the answer by @JeffBlumenthal](https://stackoverflow.com/q/17829785/850848#52499496)? – Martin Prikryl Sep 01 '22 at 11:39