Skip Ribbon Commands
Skip to main content

Quick Launch

Todd Klindt's home page > Todd Klindt's Office 365 Admin Blog > Posts > Delete _Some_ File Versions in SharePoint Online with PowerShell
September 14
Delete _Some_ File Versions in SharePoint Online with PowerShell

I recently got a fun email from a client. Their tenant had run over its storage allocation. After some quick investigation they realized that they had a few dozen files with a lot of versions, the average number of versions was over 1200 per file. Some files had over 3000 versions. The kicker is that these files were big, dozens or hundreds of MBs each. Thousands of files, 100s of MBs a piece? Pretty soon you’re talking about some real storage space! His question to me was how he could easily delete these unneeded versions quickly and easily? PowerShell, of course!

Before we get to the golden PowerShell nuggets at the end, how did they end up here in the first place? Versions have been around forever in SharePoint but in the last couple of years there was a change. As part of their strategy to protect us from ransomware, Microsoft turned on versioning for all Document Libraries in SPO, and set the maximum number of versions to 500. That way if malware encrypted your site you could just roll your documents back to an unencrypted version. Pretty clever approach. The bad news is that if you don’t know this is in place, like my customer didn’t, you can chew up a lot of space by frequently uploading large files. Back to our story…

My mancrush on the PnP PowerShell is well documented, so of course that’s the first place I looked for a solution. Sure enough, there it was, shining like a beacon of hope on a foggy night, Remove-PnPFileVersion. Do you hear angels singing? I know I do. I sent that off to my customer, dusted off my hands, and leaned back, put my hands behind my head and basked in self satisfaction. It was glorious.  Until the customer replied…

He didn’t want to delete all of the versions of a file. He wanted to something like delete all except the last 5 versions. Remove-PnPFileVersion has 2 parameter sets. One that deletes a single version (by its ID number) and one that deletes all versions. No middle ground. While my previous victory was short lived, I knew PowerShell would come through for me here too.

Long story short, I scribbled down a quick PowerShell script that will delete the file versions beyond the number you wish to keep. This customer had a CSV file of the files they wanted to prune, so I added support for that. I have posted the files on GitHub (DeleteOldVersions.ps1 and VersionDelete.csv ) and I’ll go over the mechanics here.

Here is what the CSV file looks like, if you want to use that:

The Remove-PnPFileVersion cmdlet natively handles URLs in the forms of lines 2-5. I added support for the URL having the tenant name as well because a report the customer had included that and I wanted to make it easy for them to read. I’m good like that.

Here’s the code:

First I connect to the site:
$SiteUrl =
Connect-PnPOnline -Url $SiteUrl

You’ll need to adjust those to your own situation. Then I load up the CSV file. If you don’t want to do this with a CSV file you don’t have to. You can manually put the file name in.

$FileList = Import-Csv .\VersionDelete.csv

Then I pick how many file versions I want to keep:

$VersionsToKeep = 5

Next I walk through the $FileList.

foreach($File in $FileList) {

If the FileName property has the $SiteUrl in it I take it out.

$Filename = $File.FileName.Replace($SiteUrl,"")

Then I grab all the FileVersions of the file:

$FileVersions = Get-PnPFileVersion -Url $Filename

Get-PnPFileVersion does not show the Current Version, so it will always show one fewer version than what you see in the UI. If the number of versions is greater than the version we said we wanted to keep in $VersionsToKeep then I create a list of versions in $DeleteVersionList to delete:

if ($FileVersions.Count -gt $VersionsToKeep) { 
$DeleteVersionList = ($FileVersions[0..$($FileVersions.Count - $VersionsToKeep)])

With that list in hand I walk through it and run Remove-PnPFileVersion against it. In the code in GitHub I have commented out the line (Line 33 as of 9/14/21) that actually deletes the version. You’ll have to uncomment that to do anything.

foreach($VersionToDelete in $DeleteVersionList) {
Remove-PnPFileVersion -Url $Filename -Identity $VersionToDelete.Id –Force

To make piping easy I output the versions deleted as a CustomObject:

$Output = [PSCustomObject]@{
PSTypeName = 'TKDeletedFileVersion'
Filename     = $Filename
DeletedVersion     = $($VersionToDelete.VersionLabel) 


When you look at the code you’ll notice a line at the top,
$VerbosePreference = "Continue" 

If you uncomment that line it will light up the Write-Verbose statements in the code. Set it back to SilentyContinue to make them go away.

This is what it looks like with Verbosity off:


If you need to audit which versions are being deleted you can pipe that to Export-CSV and save it to a file.

If you want to create some versions to test this with you can use the following PowerShell:

$DocLib = “Shared Documents”
Get-PnPListItem -List $Doclib | select Id,@{l="FileLeafRef";e={$_.FieldValues.FileLeafRef}}

That’ll get you the files in the Document Library. You can use this command to touch them and create 6 new versions:

0..5 | foreach {Set-PnPListItem -List $Doclib -Identity 4 -Values @{"FileLeafRef"="Building materials licences to budget for Storytelling.docx"}}

It is also possible to filter versions by date. That way instead of deleting all but the last 5 versions, you would be able to delete all of the versions older than 30 days. That’s a blog post for a different day though.





Script DeleteOldVersions.ps1 not avaliable

Dear Todd,
Can you share your script please again? It is not available on your Github.
Thanks in advance!
 on 1/29/2022 1:24 PM

Script Not available on GitHub

Hello Todd,

The links to the scripts were broken, could you re-upload them?
Thank you again for the wonderful work.
 on 6/13/2022 10:52 AM

Re: Script Not available on GitHub

Hi folks,
The files are now available. I had put them in a non-public repo. That's what happens when admins use GitHub. :)
Todd O. KlindtNo presence information on 6/20/2022 10:22 AM


Good day, Todd.
Could you re-upload the scripts since the URLs were broken?
Thank you once again for your excellent effort.
 on 7/12/2022 1:53 AM

Add Comment

Items on this list require content approval. Your submission will not appear in public views until approved by someone with proper rights. More information on content approval.


Body *

Today's date *

Select a date from the calendar.
Please enter today's date so I know you are a real person


Want a message when I reply to your comment? Put your Twitter handle here.