247

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?

2
  • 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. Commented Sep 29, 2016 at 14:22
  • 1
    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 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. Commented Aug 23, 2023 at 20:46

12 Answers 12

413

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.

Sign up to request clarification or add additional context in comments.

9 Comments

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.
If files may be in use it's also worth adding " -ErrorAction SilentlyContinue" to the RemoveItem command.
Thanks! I use $_.LastwriteTime instead of $_.CreationTime
@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.
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.
|
103

just simply (PowerShell V5)

Get-ChildItem "C:\temp" -Recurse -File | Where CreationTime -lt  (Get-Date).AddDays(-15)  | Remove-Item -Force

2 Comments

Use "LastWriteTime" if you want last modified date
I like your concise answer!
21

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

Comments

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

1 Comment

Thanks for this, esp including the 'WhatIf' switch for testing.
10

Try this:

dir C:\PURGE -recurse | 
where { ((get-date)-$_.creationTime).days -gt 15 } | 
remove-item -force

2 Comments

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?
If the directory you're working with is two directories deep a second -recurse is needed.
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

1 Comment

I've updated my answer to exclude directories now, thanks.
7

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

1 Comment

LastwriteTime is not the same as CreationTime, LastwriteTime is update each time the file is modified.
4

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

ls -file | where { (get-date) - $_.creationtime -gt 15. } | Remove-Item -Verbose

Comments

3
#----- 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"
    }
}

3 Comments

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.
@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
I'm guessing so- just stumbed across the same script here; networknet.nl/apps/wp/published/…
2
$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.

Comments

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

3 Comments

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)
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.
What's wrong for example with the answer by @JeffBlumenthal?
0

This is just a minor improvement to the already provided answers. Basically the command uses the Filter parameter to improve performance based on the following quote from Get-ChildItem

The Filter parameter is more efficient than other parameters. The FileSystem provider applies filter when the cmdlet gets the objects rather than having PowerShell filter the objects after they're retrieved.

$FolderPath = 'C:\Logs '
$FileExtension = 'log'
$OlderThan = 15 # Days.

Get-ChildItem -Path $FolderPath -File -Filter "*.$FileExtension" | Where-Object {$_.CreationTime -LT (Get-Date).AddDays(-$OlderThan)} | Remove-Item -Force -ErrorAction SilentlyContinue

If you want to traverse $FolderPath, then add Recurse to the command:

Get-ChildItem -Path $FolderPath -Recurse -File -Filter "*.$FileExtension" | Where-Object {$_.CreationTime -LT (Get-Date).AddDays(-$OlderThan)} | Remove-Item -Force -ErrorAction SilentlyContinue

If you want to include hidden and system files, then add Force to the command:

Get-ChildItem -Path $FolderPath -Force -File -Filter "*.$FileExtension" | Where-Object {$_.CreationTime -LT (Get-Date).AddDays(-$OlderThan)} | Remove-Item -Force -ErrorAction SilentlyContinue

If you want to delete files that have not been modified in $OlderThan instead of been created $OlderThan age, replace $.CreationTime with $.LastWriteTime

Get-ChildItem -Path $FolderPath -File -Filter "*.$FileExtension" | Where-Object {$_.CreationTime -LT (Get-Date).AddDays(-$OlderThan)} | Remove-Item -Force -ErrorAction SilentlyContinue

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.