Improve performance of files purge with PowerShell

Improve performance of files purge with PowerShell

Here is a technique to improve performance when you come across the task of deleting thousands of files located under many folders

 

This is a common way to get all the files meeting a criteria of “older than a specific date” from a specific folder including any sub folder if exists while filtering on a specific file extension. The file extensions can be modified or changed to *.* in order to work on all file extensions. The –recurse option is required to work on subfolders and for the file extension filtering.

   1: $days = 15;

   2: $files = Get-ChildItem $path  -recurse -include *.bak | Where-Object {$_.LastWriteTime -lt (Get-Date).AddDays(-$days) -and $_.PSIsContainer -eq $False} 

 

While the above command is good for most cases it will perform poor in cases where the destination path has many folders with many files.

I came across a case where it took that command around 45 minutes just to complete and populate the $files variable before getting to the actual purge phase.

 

This is the option I ended up with after various tries and different approaches.

Its performed so much faster in may case where I had a file system with over 800,000 files to deal with and a complex directory structure.

The trick is using the dir command within a cmd window (“C:\Windows\System32\cmd.exe”) and the appropriate switches.

   1: $folders = cmd.exe /c "dir E:\LPR_pic /s /b /ad";

 

 

The complete script

   1: #Set-ExecutionPolicy RemoteSigned

   2:  

   3: <#

   4:     20160520 - Yaniv Etrogi 

   5:     Purge files

   6:  

   7:     Paramters:

   8:         $path - The root path we work on recursevly

   9:         $delete_only_archived_files - 1 specifies that only files with the Archive attribute on will be purged

  10:                                       0 specifies that all files will be purged (disregard Archive attribute)

  11:         $days - The number of retention days. Only files older than the (current date - $days) will be purged

  12:                 Note that this parameter is assigned multipple times

  13:         $do_delete - 1 specifies that purge takes place 

  14:                      0 specifies only printing (no purge)

  15: #>

  16:  

  17: Set-Location C:

  18: $Attribute = [io.fileattributes]::Archive

  19: $UserInteractive = [Environment]::UserInteractive

  20: $delete_only_archived_files = 1

  21: $do_delete = 1

  22: $path = "E:\LPR_pic\"

  23: $days = 120

  24:  

  25:  

  26: #$folders = Get-ChildItem $path -Recurse | ?{ $_.PSIsContainer } |Select-Object -ExpandProperty FullName

  27: #$folders = Get-ChildItem $path -Recurse | WHERE { $_.PSIsContainer -match"Directory"} |Select-Object -ExpandProperty FullName

  28:  

  29: # Populate an array with folders only

  30: $folders = cmd.exe /c "dir E:\LPR_pic /s /b /ad";

  31:  

  32:  

  33: # Loop over the folders array

  34: foreach($folder in $folders)

  35: {       

  36:     # If the folder is empty delete it

  37:     if ( (Get-ChildItem $folder | Measure-Object).Count -eq 0)

  38:     {

  39:         if ($UserInteractive -eq "True" ) {Write-Host 'Deleting folder...' $folder -ForegroundColor Red}

  40:         Remove-Item -force -Recurse $folder;

  41:     }

  42:     else

  43:     {

  44:         if ($UserInteractive -eq "True" ) {Write-Host 'Processing folder...' $folder -ForegroundColor Green}

  45:         $files = Get-ChildItem $folder | Where-Object {$_.LastWriteTime -lt (Get-Date).AddDays(-$days) -and $_.PSIsContainer -eq $False} 

  46:         

  47:         # Loop over the files in each folder

  48:         foreach($file in $files)

  49:         {                

  50:             if ($do_delete -eq 1)

  51:             {   

  52:                 if ($UserInteractive -eq "True" ) {Write-Host -ForegroundColor White $file.FullName }                                         

  53:                 $file.Delete();                

  54:             }

  55:             else

  56:             {

  57:                 if ($UserInteractive -eq "True" ) {Write-Host -ForegroundColor Yellow $file.FullName }                            

  58:             }

  59:         } 

  60:     

  61:     }   

  62: }

  63:  

  64:  

The following two tabs change content below.
Yaniv Etrogi is an SQL Server consultant. He loves SQL Server and he is passionate about Performance Tuning, Automation and Monitoring.

Leave a Comment

Your email address will not be published. Required fields are marked *