How To Find And Remove Old Files In PowerShell

How To Find And Remove Old Files In PowerShell

This article explains how to list and remove old files in a folder using PowerShell.

Question

So I have all these files in my backup folder. How can I keep only the files modified at most seven days ago, whilst removing the rest?

Short Answer

We can use a simple chain like this:

Get-ChildItem -Recurse |

    # change the extension as appropriate
    ?{ $_.Extension -eq ".bak" } |

    # change the time window as appropriate
    ?{ $_.LastWriteTime -lt (Get-Date).AddDays(-7) } |

    # now remove the results
    Remove-Item

We can then add or remove filters to this pattern as appropriate to your scenario.

So what more stuff can we add?

Long Answer

To see a list of all filters, we can pipe a file object to Get-Member.

Get-ChildItem | Select-Object -First 1 | Get-Member

It doesn’t matter where or on what files we run this. The result will be the same list of file properties, which we can see below:

   TypeName: System.IO.DirectoryInfo

Name                      MemberType     Definition                                                                         
----                      ----------     ----------                                                                         
Mode                      CodeProperty   System.String Mode{get=Mode;}                                                      
Create                    Method         void Create(), void Create(System.Security.AccessControl.DirectorySecurity direc...
CreateObjRef              Method         System.Runtime.Remoting.ObjRef CreateObjRef(type requestedType)                    
CreateSubdirectory        Method         System.IO.DirectoryInfo CreateSubdirectory(string path), System.IO.DirectoryInfo...
Delete                    Method         void Delete(), void Delete(bool recursive)                                         
EnumerateDirectories      Method         System.Collections.Generic.IEnumerable[System.IO.DirectoryInfo] EnumerateDirecto...
EnumerateFiles            Method         System.Collections.Generic.IEnumerable[System.IO.FileInfo] EnumerateFiles(), Sys...
EnumerateFileSystemInfos  Method         System.Collections.Generic.IEnumerable[System.IO.FileSystemInfo] EnumerateFileSy...
Equals                    Method         bool Equals(System.Object obj)                                                     
GetAccessControl          Method         System.Security.AccessControl.DirectorySecurity GetAccessControl(), System.Secur...
GetDirectories            Method         System.IO.DirectoryInfo[] GetDirectories(), System.IO.DirectoryInfo[] GetDirecto...
GetFiles                  Method         System.IO.FileInfo[] GetFiles(string searchPattern), System.IO.FileInfo[] GetFil...
GetFileSystemInfos        Method         System.IO.FileSystemInfo[] GetFileSystemInfos(string searchPattern), System.IO.F...
GetHashCode               Method         int GetHashCode()                                                                  
GetLifetimeService        Method         System.Object GetLifetimeService()                                                 
GetObjectData             Method         void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.R...
GetType                   Method         type GetType()                                                                     
InitializeLifetimeService Method         System.Object InitializeLifetimeService()                                          
MoveTo                    Method         void MoveTo(string destDirName)                                                    
Refresh                   Method         void Refresh()                                                                     
SetAccessControl          Method         void SetAccessControl(System.Security.AccessControl.DirectorySecurity directoryS...
ToString                  Method         string ToString()                                                                  
PSChildName               NoteProperty   System.String PSChildName=folder                                                   
PSDrive                   NoteProperty   System.Management.Automation.PSDriveInfo PSDrive=C                                 
PSIsContainer             NoteProperty   System.Boolean PSIsContainer=True                                                  
PSParentPath              NoteProperty   System.String PSParentPath=Microsoft.PowerShell.CoreFileSystem::C:WorkTest Files
PSPath                    NoteProperty   System.String PSPath=Microsoft.PowerShell.CoreFileSystem::C:WorkTest Filesfo...
PSProvider                NoteProperty   System.Management.Automation.ProviderInfo PSProvider=Microsoft.PowerShell.CoreF...
Attributes                Property       System.IO.FileAttributes Attributes {get;set;}                                     
CreationTime              Property       datetime CreationTime {get;set;}                                                   
CreationTimeUtc           Property       datetime CreationTimeUtc {get;set;}                                                
Exists                    Property       bool Exists {get;}                                                                 
Extension                 Property       string Extension {get;}                                                            
FullName                  Property       string FullName {get;}                                                             
LastAccessTime            Property       datetime LastAccessTime {get;set;}                                                 
LastAccessTimeUtc         Property       datetime LastAccessTimeUtc {get;set;}                                              
LastWriteTime             Property       datetime LastWriteTime {get;set;}                                                  
LastWriteTimeUtc          Property       datetime LastWriteTimeUtc {get;set;}                                               
Name                      Property       string Name {get;}                                                                 
Parent                    Property       System.IO.DirectoryInfo Parent {get;}                                              
Root                      Property       System.IO.DirectoryInfo Root {get;}                                                
BaseName                  ScriptProperty System.Object BaseName {get=$this.Name;}      

Do you notice there is also a CreationTime property in there? We can make use of this property to remove files that changed more than a week ago, yet keep files that were created less than a week ago.

This sounds confusing and illogical, doesn’t it? How can a file have been created after it was changed? It doesn’t make sense.

Yet this is common in Windows as it happens all the time we copy a file from one place to another. When a file is copied in Windows, its CreationTime is set as the date the copy occured, while its LastWriteTime is inherited from the original copy. This makes the file appear like it was created after it was modified though, of course, it wasn’t.

In the previous example, if we wanted to take this into consideration and avoid removing newly copied files, we could simply add another criterion:

Get-ChildItem -Recurse |

    # change the extension as appropriate
    ?{ $_.Extension -eq ".csv" } |

    # change the modified time window as appropriate
    ?{ $_.LastWriteTime -lt (Get-Date).AddDays(-7) } |

    # change the created time window as appropriate
    ?{ $_.CreationTime -lt (Get-Date).Add(-7) } |

    Remove-Item

And that’s it. Easy, isn’t it?

Jorge Candeias's Picture

About Jorge Candeias

Jorge helps organizations build high-performing solutions on the Microsoft tech stack.

London, United Kingdom https://jorgecandeias.github.io