SharePoint Online: Delete Version History using PnP PowerShell

Requirement: Delete version history in SharePoint Online.

How to Delete Versions in SharePoint Online?

If you’ve been managing SharePoint Online for any time, you know that keeping your environment clean and organized is essential. One such way to clean it up is by deleting older versions of documents and files, as old versions can take up a lot of storage space. This blog post will show you how to remove older versions of documents in SharePoint Online using PowerShell and automate the cleanup process.

To delete previous versions of a file in SharePoint Online, follow these steps:

  1. Navigate to your SharePoint Online document library, select the file, and click on “Version History” from the toolbar. (or Select “Version History” from the context menu of the document)
  2. On the version history page, You can choose “Delete” from the context menu of the particular version. To delete all versions of a document or list item, click the “Delete All Versions” link on the Version History page and then confirm the prompt.
    sharepoint online delete versions powershell

Delete All Versions of a File using PnP PowerShell

SharePoint Online version history helps to keep track of changes made to a document. However, sometimes it may be necessary to delete version history to free up storage space or for compliance purposes. Let’s see how to delete version history in SharePoint Online using PowerShell.

Here is how to delete all versions of a file in the SharePoint Online document library using PowerShell:

#Parameters
$SiteURL = "https://crescent.sharepoint.com/sites/marketing"
$FileURL= "/sites/marketing/Branding/Invoice.xlsx"
 
#Connect to PnP Online
Connect-PnPOnline -Url $SiteURL -Interactive
 
#Get all versions of the File
$Versions = Get-PnPFileVersion -Url $FileURL

#Delete all versions of the File
$Versions.DeleteAll()
Invoke-PnPQuery

SharePoint Online: Delete Version History using PnP PowerShell

Let’s delete all versions of all items in a list or library using PowerShell.

#Config Variables
$SiteURL = "https://Crescent.sharepoint.com/sites/marketing"
$ListName="Documents"

#Connect to PnP Online
Connect-PnPOnline -Url $SiteURL -Credentials (Get-Credential)

#Get the Context
$Ctx= Get-PnPContext

#Get All Items from the List - Exclude 'Folder' List Items
$ListItems = Get-PnPListItem -List $ListName -PageSize 2000 | Where {$_.FileSystemObjectType -eq "File"}

ForEach ($Item in $ListItems)
{
    #Get File Versions
    $File = $Item.File
    $Versions = $File.Versions
    $Ctx.Load($File)
    $Ctx.Load($Versions)
    $Ctx.ExecuteQuery()
    Write-host -f Yellow "Scanning File:"$File.Name
    
    If($Versions.Count -gt 0)
    {
        #Delete all versions
        $Versions.DeleteAll()
        $Ctx.ExecuteQuery()
        Write-Host -f Green "Deleted All Previous Versions of the File:"$File.Name
    }
}

We can clear all previous versions of all the files in a SharePoint Online document library using PnP PowerShell as:

#Parameters
$SiteURL = "https://crescent.sharepoint.com/sites/IC"
$LibraryName = "Energy"
 
Try {
    #Connect to PnP Online
    Connect-PnPOnline -Url $SiteURL -Interactive

    #Get the Library
    $Library = Get-PnPList -Identity $LibraryName 
    $global:counter=0

    #Get All Items from the List - Get 'Files
    $ListItems = Get-PnPListItem -List $Library -Fields FileLeafRef,FileRef -PageSize 2000 -ScriptBlock { Param($items) $global:counter += $items.Count; Write-Progress `
                    -PercentComplete ($global:Counter / ($Library.ItemCount) * 100) -Activity "Getting Files of '$($Library.Title)'" `
                       -Status "Processing Files $global:Counter of $($Library.ItemCount)";} | Where {($_.FileSystemObjectType -eq "File")} 
    Write-Progress -Activity "Completed Retrieving Files!" -Completed

    #Loop through each file
    $global:counter=1
    ForEach ($Item in $ListItems)
    {
        #Get File and File Versions
        $Versions = Get-PnPFileVersion -Url $Item.FieldValues.FileRef
        Write-host -f Yellow "Scanning File ($global:counter of $($Library.ItemCount)) : $($Item.FieldValues.FileRef)"
      
        If($Versions.Count -gt 0)
        {
            #Delete all versions
            $Versions.DeleteAll()
            Invoke-PnPQuery
            Write-Host -f Green "`tDeleted All Previous Versions of the File!" #"$Item.FieldValues.FileRef
        }
        $global:counter++
    }
}
Catch {
    write-host -f Red "Error Cleaning up Version History!" $_.Exception.Message
}

PowerShell to Clear Previous Versions Folder by Folder

Here is a different approach to clear previous versions of all files on libraries with less than 5000 items.

#Parameters
$SiteURL = "https://crescent.sharepoint.com/sites/marketing"
$LibraryName ="Documents"

#Function to Clear all File versions in a Folder
Function Cleanup-Versions([Microsoft.SharePoint.Client.Folder]$Folder)
{
    Write-host "Processing Folder:"$Folder.ServerRelativeUrl -f Yellow
    #Get the Site Relative URL of the folder
    $FolderSiteRelativeURL = $Folder.ServerRelativeURL.Replace($Web.ServerRelativeURL,[string]::Empty)

    #Get All Files from the folder    
    $Files = Get-PnPFolderItem -FolderSiteRelativeUrl $FolderSiteRelativeURL -ItemType File
    
    #Iterate through each file
    ForEach ($File in $Files)
    {
        #Get File Versions
        $Versions = Get-PnPProperty -ClientObject $File -Property Versions 
        Write-host -f Yellow "`tScanning File:"$File.Name
     
        If($Versions.Count -gt 0)
        {
            #Delete all versions
            $Versions.DeleteAll()
            Invoke-PnPQuery
            Write-Host -f Green "`t`tDeleted All Previous Versions of the File:"$File.Name
        }
    }

    #Get Sub-folders from the folder - Exclude "Forms" and Hidden folders
    $SubFolders = Get-PnPFolderItem -FolderSiteRelativeUrl $FolderSiteRelativeURL -ItemType Folder | Where {($_.Name -ne "Forms") -and (-Not($_.Name.StartsWith("_")))}
    Foreach($SubFolder in $SubFolders)
    {
        #Call the function recursively
        Cleanup-Versions -Folder $SubFolder     
    }
}
 
#Connect to PnP Online
Connect-PnPOnline -Url $SiteURL -Interactive
$Web = Get-PnPWeb

#Get the Root Folder of the Library
$RootFolder = Get-PnPList -Identity $LibraryName -Includes RootFolder | Select -ExpandProperty RootFolder

#Call the function with Root Folder of the Library
Cleanup-Versions -Folder $RootFolder

You can clean up previous versions of all files from a folder by replacing Line#45 with “$RootFolder = Get-PnPFolder -Url $FolderServerRelativeURL”.

Keep the Last Five Versions and Delete the Rest:

Going through the version history page and deleting it one by one is cumbersome. Here is the PnP PowerShell to keep the last ‘N’ versions and delete all others.

#Parameters
$SiteURL = "https://crescent.sharepoint.com/sites/Funds"
$ListName = "Documents"
$VersionsToKeep = 5
 
#Connect to PnP Online
Connect-PnPOnline -Url $SiteURL -UseWebLogin

#Get the Document Library
$List = Get-PnPList -Identity $ListName
 
#Get the Context
$Ctx= Get-PnPContext

$global:counter=0 
#Get All Items from the List - Get 'Files
$ListItems = Get-PnPListItem -List $ListName -Fields FileLeafRef -PageSize 2000 -ScriptBlock { Param($items) $global:counter += $items.Count; Write-Progress `
                -PercentComplete ($global:Counter / ($List.ItemCount) * 100) -Activity "Getting Files of '$($List.Title)'" `
                    -Status "Processing Files $global:Counter of $($List.ItemCount)";} | Where {($_.FileSystemObjectType -eq "File")}
Write-Progress -Activity "Completed Retrieving Files!" -Completed

$TotalFiles = $ListItems.count
$Counter = 1 
ForEach ($Item in $ListItems)
{
    #Get File Versions
    $File = $Item.File
    $Versions = $File.Versions
    $Ctx.Load($File)
    $Ctx.Load($Versions)
    $Ctx.ExecuteQuery()
 
    Write-host -f Yellow "Scanning File ($Counter of $TotalFiles):"$Item.FieldValues.FileRef
    $VersionsCount = $Versions.Count
    $VersionsToDelete = $VersionsCount - $VersionsToKeep
    If($VersionsToDelete -gt 0)
    {
        write-host -f Cyan "`t Total Number of Versions of the File:" $VersionsCount
        $VersionCounter= 0
        #Delete versions
        For($i=0; $i -lt $VersionsToDelete; $i++)
        {
            If($Versions[$VersionCounter].IsCurrentVersion)
            {
                $VersionCounter++
                Write-host -f Magenta "`t`t Retaining Current Major Version:" $Versions[$VersionCounter].VersionLabel
                Continue
            }
            Write-host -f Cyan "`t Deleting Version:" $Versions[$VersionCounter].VersionLabel
            $Versions[$VersionCounter].DeleteObject()
        }
        $Ctx.ExecuteQuery()
        Write-Host -f Green "`t Version History is cleaned for the File:"$File.Name
    }
    $Counter++
}

How about cleaning up the version history for all document libraries on a site?

#Config Parameters
$SiteURL = "https://crescent.sharepoint.com/sites/marketing"
$VersionsToKeep = 5

Try { 
    #Connect to PnP Online
    Connect-PnPOnline -Url $SiteURL -Interactive

    #Get the Context
    $Ctx= Get-PnPContext

    #Exclude certain libraries
    $ExcludedLists = @("Form Templates", "Preservation Hold Library","Site Assets", "Pages", "Site Pages", "Images",
                            "Site Collection Documents", "Site Collection Images","Style Library")

    #Get All document libraries
    $DocumentLibraries = Get-PnPList | Where-Object {$_.BaseType -eq "DocumentLibrary" -and $_.Title -notin $ExcludedLists -and $_.Hidden -eq $false}

    #Iterate through each document library
    ForEach($Library in $DocumentLibraries)
    {
        Write-host "Processing Document Library:"$Library.Title -f Magenta

        #Get All Items from the List - Exclude 'Folder' List Items
        $ListItems = Get-PnPListItem -List $Library -PageSize 2000 | Where {$_.FileSystemObjectType -eq "File"}

        #Loop through each file
        ForEach ($Item in $ListItems)
        {
            #Get File Versions
            $File = $Item.File
            $Versions = $File.Versions
            $Ctx.Load($File)
            $Ctx.Load($Versions)
            $Ctx.ExecuteQuery()
 
            Write-host -f Yellow "`tScanning File:"$File.Name
            $VersionsCount = $Versions.Count
            $VersionsToDelete = $VersionsCount - $VersionsToKeep
            If($VersionsToDelete -gt 0)
            {
                write-host -f Cyan "`t Total Number of Versions of the File:" $VersionsCount
                $VersionCounter= 0
                #Delete versions
                For($i=0; $i -lt $VersionsToDelete; $i++)
                {
                    If($Versions[$VersionCounter].IsCurrentVersion)
                    {
                       $VersionCounter++
                       Write-host -f Magenta "`t`t Retaining Current Major Version:"$Versions[$VersionCounter].VersionLabel
                       Continue
                    }
                    Write-host -f Cyan "`t Deleting Version:" $Versions[$VersionCounter].VersionLabel
                    $Versions[$VersionCounter].DeleteObject()
                }
                $Ctx.ExecuteQuery()
                Write-Host -f Green "`t Version History is cleaned for the File:"$File.Name
            }
        }
    }
}
Catch {
    write-host -f Red "Error Cleaning up Version History!" $_.Exception.Message
}

You can apply this cleanup to all files within a specific folder or sub-folder by:

$ListItems = Get-PnPListItem -List $ListName -FolderServerRelativeUrl $FolderServerRelativeURL -PageSize 2000

This script leaves the recent ‘N’ number of versions and deletes all previous versions of the documents. To clean up older versions in SharePoint Online using PowerShell CSOM, refer: SharePoint Online: Delete Version History using PowerShell CSOM

Don’t forget to set a limit for the number of versions under:  List/Library Settings >> Versioning settings to prevent any further versions growing beyond your limit.

Conclusion:

In conclusion, deleting version history in SharePoint Online can be necessary for various reasons, including freeing up storage space and compliance purposes. While it is possible to delete version history manually, this can be a time-consuming process, especially if you have a large number of documents. However, using PowerShell can make this process more efficient and straightforward. With the script provided in this guide, you can easily delete version history in SharePoint Online in just a few steps. By automating this task, you can save valuable time and ensure that your SharePoint Online environment remains organized and optimized for your needs.

Salaudeen Rajack

Salaudeen Rajack - SharePoint Expert with Two decades of SharePoint Experience. Love to Share my knowledge and experience with the SharePoint community, through real-time articles!

92 thoughts on “SharePoint Online: Delete Version History using PnP PowerShell

  • At the 1 hour point the PnP seems to stop.
    Error Cleaning up Version History! Exception calling “ExecuteQuery” with “0” argument(s): “The SSL connection could not be established, see inner exception.”

    Is this an authentication timeout to the tenant?

    Reply
  • Thank you so much for sharing your knowledge Salaudeen. I was really nervous running a bulk script against a 1.5TB sharepoint installation but the PnP script worked without any issues except for first setting it up. You’re awesome!

    Reply
  • Hi all,

    Thanks so much for this, it works great.

    Question: How can we specify a particular folder within the document library on the “Versions to keep” entry. Reason being, it works great on the entire document library but we sometimes only want to chose a particular folder within that document library.

    Reply
    • i see this underneath:
      $ListItems = Get-PnPListItem -List $ListName -FolderServerRelativeUrl $FolderServerRelativeURL -PageSize 2000

      But how do you specify which folder?

      Thanks

      Reply
  • Thanks for this.
    Was facing issue with file versions that were quite large. ie in the thousands.
    Set to delete all but keep 101 versions.
    Would process most files fine, but these larger ones, it would delete a chunk (seems to be 100 versions) then error with
    “Exception calling “ExecuteQuery” with “0” argument(s): “The remote server returned an error: (503) Service Unavailable.”:”

    I saw a comment you made about using the below:
    Try: $Ctx.RequestTimeout = [System.Threading.Timeout]::Infinite or call $Ctx.ExecuteQuery() after each Delete.

    $Ctx.RequestTimeout = [System.Threading.Timeout]::Infinite made no difference.
    $Ctx.ExecuteQuery() so far seems to be working, but alas a lot slower in the deletion.

    One thing I did notice, it’s delete all the odd versions?

    Reply
  • thank you for this extensive collection of useful scripts. It helps me a lot.

    I used your script to delete all versions older than 5 days. I had rewritten it a bit to apply it over all our 500 pages.

    For reasons I now had to upgrade to the PnP module and PowerShell 7. Additionally, I also registered an app in Azure to make authentication easier. So I want to combine two of your scripts to get a better handle on SharePoint online.

    The login via an appregistration works. but I would now need to retrieve all sites of the tenant to use them as variables.
    Then I would run them through your script. As a SChleife so to speak. For each!
    I fail now to output all pages with PnP.

    With the normal modul the command was: $Sites = Get-SPOSite -Limit ALL

    I am glad about a message

    Reply
    • Hello Alex,
      here is a small script snippet that we use in our company. Where can I find the login and how to set the app registration?
      —-
      Try {
      #Connect to Admin Center
      Connect-PnPOnline -Url $AdminSiteURL -Interactive

      #Get All Site collections
      $SitesCollection = Get-PnPTenantSite

      #Loop through each site collection
      ForEach($Site in $SitesCollection)
      {
      #Set-PnPTenantSite -Url $Site.Url -Owners $SiteCollAdmin1
      #Set-PnPTenantSite -Url $Site.Url -Owners $SiteCollAdmin2
      Write-Host -F Blue “SiteAdmins Hr. Warratz und Hr. Gorontzi hinzugefügt zur Sharepoint Site: $($Site.URL)”

      $Site | SELECT-Object “URL” | Export-CSV -Append -Path D:\SharePoint-Site-Bereinigung.csv -UseQuotes AsNeeded
      }
      }
      Catch {
      Write-Host -f Red “Error:” $_.Exception.Message
      }

      (Get-Content D:\SharePoint-Site-Bereinigung.csv | Select-Object -Skip 1) | Set-Content D:\SharePoint-Site-Bereinigung.csv

      #Config Parameters
      $CSV = Get-Content D:\SharePoint-Site-Bereinigung.csv
      $VersionsToKeep = 5

      Reply
      • Hi Angrolsch,

        thank you for sharing your snippet.

        here you find an answer for your question:
        https://www.sharepointdiary.com/2022/10/connect-to-sharepoint-online-using-azure-ad-app-id-from-powershell.html

        Reply
    • i managed to solve my question, thanks to angrolsch. that was my missing link.

      Unfortunatley sometime i got this error:

      Scanning File: FRESNO~1.JPG
      Error Cleaning up Version History! Exception calling “ExecuteQuery” with “0” argument(s): “Operation is not valid due to the current state of the object.”
      Processing Document Library: Dokumente
      Scanning File: 2022_06_08_Academie_6-1OG_Anforderung_JS.pdf

      Reply
  • Hi Salaudeen Rajack,

    i am using the power shell script to clean version history for all complete site library and keep only 5 version .
    but at any instance of time for any library it gives me
    Scanning File: 10028347.MW202.210707.3114359.test.docx
    Total Number of Versions of the File: 17
    Deleted Version: 5.1
    Deleted Version: 5.2
    Deleted Version: 5.3
    Deleted Version: 5.4
    Deleted Version: 5.5
    Deleted Version: 5.6
    Deleted Version: 5.7
    Deleted Version: 5.8
    Deleted Version: 5.9
    Deleted Version: 5.10
    Deleted Version: 5.11
    Deleted Version: 5.12
    Error Cleaning up Version History! Exception calling “ExecuteQuery” with “0” argument(s): “You cannot delete the current version.”
    can you please help me to get the correct working script.its an pnp power shell script

    Reply
    • This is because: You have minor versions enabled and published a previous version as “Major Version”. The script has been updated to accommodate this scenario now!

      Reply
  • Hi Salaudeen,
    First of all, great job! I’ve used a lot of your wonderful script!
    I’m wondering if you could help me…I was trying to clean all version (except for the 15 newest) of all document library of a SPO site, but I got this error: Error Cleaning up Version History! Exception calling “ExecuteQuery” with “0” argument(s): “The remote server returned an error: (429).”

    Reply
    • I have the same problem. have you found a solution how to implement “pause” between requests to help to reduce throttling?

      Reply
  • Hi,
    great script thank you for taking time to do it.
    I’ve just ran it now on a large list, no issues ran successfully and deleted the relevant versions…however when I check the site metrics it hasn’t changed and then when I check the versioning of some of the files they are all still there. Is this because it needs time to update due to the size of the list? Thanks

    Reply
    • G’day Ben,

      It took just under 24 hours from when I started the clean up to when SharePoint Admin Center and the corresponding Team Sites started noticing the changes.

      I contacted Microsoft Support (level 1) and they didn’t know of any powershell command to speed this process up or make it immediate.

      Reply
  • This is an amazingly useful script – thank you for sharing.

    I have one department who has a large library (95000+) items which then exceed the List View Threshold.

    I want to apply the version clean-up script to a couple of specific folders of this list, but when I add the -FolderServerRelativeUrl parameter, it throws this error:

    “Error Cleaning up Version History! The attempted operation is prohibited because it exceeds the list view threshold.”

    Without that parameter the script runs fine – is there a way to make this work without reorganising the whole library?

    Reply
    • I’m getting the same issue when targeting just a folder.
      Doing the whole library no problems.
      tried several options, but alas non work so far

      Reply
  • Thank you for your wonderful site – I have benefited greatly from you sharing your knowledge!
    In the script “Keep the Last Five Versions and Delete the Rest:”, when there are major and minor versions, this script (as presently written) produces an error when the current major (published) version is among the versions targeted to delete (i.e not within the “5” kept versions.). I made the below modification to address this (there’s probably a better way, but I’m just an amateur hack in Power-Shell).
    write-host -f Cyan “`t Total Number of Versions of the File:” $VersionsCount
    #Delete versions
    $keepCounter = 0
    For($i=$VersionsCount -1; $i -ge 0; $i–)
    {

    if ($keepCounter -lt $VersionsToKeep){
    $keepcounter ++
    Write-host -f Black -b White “`t`t Retaining posterity Version:” $Versions[$i].VersionLabel
    }
    elseif($Versions[$i].IsCurrentVersion){
    Write-host -f red -b white “`t`t Retaining Current Major Version:” $Versions[$i].VersionLabel
    }
    else{
    Write-host -f Cyan “`t`t Deleting Version:” $Versions[$i].VersionLabel
    $Versions[$i].DeleteObject()
    }
    }

    Reply
  • Hi, nice scripts!
    But when using “Keep Last Five Versions and Delete the Rest” is there a way to specify the sub folder in a library? I mean I’ve tried to ran the script with the line you’ve mentioned above, but I keep getting the message “The attempted operation is prohibited because it exceeds the list view threshold”

    Reply
  • Can someone help me to improve the script ignoring pdf files? I want to focusing on .xlsx, pptx and docx only (my main problem.

    Reply
    • Just Filter the Files with: $DocumentItems = $ListItems | Where { $_[“File_x0020_Type”] -in (“docx”, “xlsx”, “pptx”)}

      Reply
  • For anyone else dealing with large lists, I found some info about respecting Retry-After headers but couldn’t find any documentation regarding how to use them in a try/catch.
    Instead, I slowed down my code to ensure I’d not exceed the rate limits for our license count by using a 100ms start-sleep in each cycle.

    Reply
  • $Versions.DeleteAll() throws an error as an invalid method now.

    Reply
  • Hello, love the website! But I have a question: Is it possible to delete versions that are older than 2 Weeks? With our current setup it is difficult to set a specific number for the allowed versions. Thanks!

    Reply
  • Will this work for document libraries with say up to 100,000 items in?

    Reply
  • What about minor versions? is it possible to keep only the latest 5?

    Reply
  • Hi,
    very useful script.
    but any way to go through error 429 ?
    i cant clear my data cause of this
    cordialy

    Reply
    • This is my issue as well.

      Reply
  • If we wanted to delete only version 1.0?

    Is that possible, if so how would we acheive this?

    Thanks

    Reply
  • Hi

    Your scripts are great – I am using a modified version of Keep Last Five Versions and getting the timeout. I will try the notes from above in the previous comments.

    As a thought – can we filter to only look at files with version history – is this possible?

    Thanks!

    Reply
  • Salaudeen,
    Thank you for this and all the excellent examples of using PowerShell to manage SharePoint!!
    I have a scenario where we would like to delete all File Versions where the Modified date is older than 90 days. The above does that but is it possible to, in an attempt to avoid traversing potentially tens of thousands of files through the folder structure within a Library, to query the List to return ONLY the Files which contain Versions? If feels like have the smaller subset returned during the initial query for the List items would make this run faster.
    Thoughts?
    Thanks, Michael

    Reply
  • Hi
    I am so excited to have found this site, it is extremely informative! I hope you don’t mind if I ask a question about Online SharePoint Size quota

    We have a site which is getting too full (based on internal size limits) and we need to move a lot of documents. Irritatingly, this process (no matter what we try) adds new versions to all files, thus increasing the storage size as we go.

    I will be investigating the above scripts for stripping out Versions, but would like to better understand the “White Space” referred to at the beginning of this thread.

    So, we move a small folder with a few files in, from SharePoint site 1 to site 2.

    The files all now have 2 versions instead of 1 and the size is therefore doubled. So, I “Delete All Versions” from each file and I also go and delete them again from the Recycle Bin.

    However, when looking at the folder size of the folder I moved, in it’s new (site 2) location, it tells me that the Size is still much higher than it should have been – if I drill in, it shows one file with an apparent file size of 1.6MB while if I then go to the lowest level, looking in the “Version History” I can see there is only 1 version of the document with a size of 585kb

    So, is the “Total Size” reported actually misleading and the space used is considerably less than the Storage Metrics are suggesting?

    Reply
    • Storage Metrics shown on the site are not Real-time metrics. It takes a while to update!

      Reply
  • How can I run from several sites.
    I have an excel with more than 800 sites.
    How can i make it work to run the power shell script to all sites. for deleting version history in all sites from my share point.

    Reply
    • You can wrap the last script in this post inside a Function and call the function with SiteURL parameter.

      Reply
  • For($i=0; $i -lt $VersionsToDelete; $i++)
    {
    write-host -f Cyan “`t Deleting Version:” $Versions[0].VersionLabel
    $Versions[0].DeleteObject()
    }

    $Versions[0].DeleteObject() ->>> In the loop you trying delete the same object [0],
    has to be fixed to: $Versions[$i].DeleteObject()

    Reply
    • It doesn’t work that way! When you delete the 0th element, the object in the 1st position automatically becomes the 0th object in the array.

      Reply
      • Hi!
        Yes, you’re looping using ‘Foreach’ loop, in my case I’m using ‘Foreach-Object’ :

        $ListItems = Get-PnPListItem -List $ListName -PageSize 500 | Where-Object {($_.FileSystemObjectType -eq “File”)} -ErrorAction Continue | % {

        In this way it works precisely as needed:-)

        Reply
  • Hi There, and many thanks for your wonderful scripts. I am having trouble understanding how to run the script against just 1 folder in a document library. I have managed to run the script against the whole document library and the script works fine. I am using the “PowerShell to Clear Previous Versions Folder by Folder” and also have seen the note “You can clean up previous versions of all files from a folder by replacing Line#45 with “$RootFolder = Get-PnPFolder -Url $FolderServerRelativeURL”.$. Still don’t quite know how to proceed. Any help would be much appreciated.

    Thank you

    Reply
  • Hi Salaudeen,

    thanks for this code. In the code for delete all versions for all document libraries in a site, I’m trying to apply filter to only non-Microsoft files – so I tried putting in the check using $File.Name with the extension using notlike switch , but it does not seem to filter, it still deleting the Microsoft Office file versions. Any idea ? thanks.

    #Get File Versions
    $File = $Item.File
    $Versions = $File.Versions
    $Ctx.Load($File)
    $Ctx.Load($Versions)
    $Ctx.ExecuteQuery()

    if (($File.Name -notlike “.docx”) -or ($File.Name -notlike “.xlsx”) -or ($File.Name -notlike “.pptx”))
    {
    Write-host -f Yellow “`tScanning File:”$File.Name
    $VersionsCount = $Versions.Count
    $VersionsToDelete = $VersionsCount – $VersionsToKeep
    If($VersionsToDelete -gt 0)
    {
    write-host -f Cyan “`t Total Number of Versions of the File:” $VersionsCount
    #Delete versions
    For($i=0; $i -lt $VersionsToDelete; $i++)
    {
    $Versions[0].DeleteObject()
    Write-host -f Cyan “`t`t Deleted Version:” $Versions[0].VersionLabel
    }
    $Ctx.ExecuteQuery()
    Write-Host -f Green “`t Version History is cleaned for the File:”$File.Name
    }
    }

    Reply
    • Never mind found a solution using the following –
      $ListItems = Get-PnPListItem -List $Library -PageSize 2000 | Where {$_.FileSystemObjectType -eq “File” -and $_.FieldValues.File_x0020_Type -notin (“docx”,”xlsx”,”pptx”)}

      Reply
  • Hi Saludeen, I’m concerned about the performance overhead from having to loop through every file in every document library to remove the older versions of documents, when reducing from the default of 500 down to 10. In another article (https://www.sharepointdiary.com/2011/01/limit-versioning-and-delete-old-versions-in-sharepoint.html) you cover how to force an empty update on a list, like so

    #Perform a empty update – without creating new version, so that versioning changes will take effect
    $item.SystemUpdate($false)

    Is there a PNPonline equivalent approach that can be used, or do we need to iterate through every document in the library?

    Reply
  • This is fantastic, thank you! How can this be adjusted to run on sites with more than 999 files?

    Reply
  • Hi There,

    I see that more of the users are having this issue with the too many requests. “Exception calling “ExecuteQuery” with “0” argument(s):”

    I’ve read that you had 2 solutions for this:
    1. Try: $Ctx.RequestTimeout = [System.Threading.Timeout]::Infinite or call $Ctx.ExecuteQuery() after each Delete operation!

    2. You can mitigate by calling $Ctx.ExecuteQuery right after the operation such as: $Versions[0].DeleteObject()

    I am not that type of scripting guy, but when executing the second solution, it will return the same error.
    For the first solution i have no idea where to add this request timeout.

    Could you help me out?

    Thanks,
    Kind regards,
    Bart Maatje

    Reply
  • Would you be able to add line to write out to text file to tell what file was touched as log?

    Reply
  • I have found that after a week since I deleted a large amount of version history files that the total reported size of our tenant in the admin center has not reduced, despite the fact that the site where I deleted the version history is showing a lot less storage usage in the admin centre. I may have to open a MS ticket

    Reply
    • Try this:

      • Empty both the recycle bins
      • Exclude the site from any retention hold policy for time being (Before start deleting the versions)
      Reply
      • if the site had any previous retention policy which creates the Preservation Hold library, any deleted items will still move to PHL even after emptying recycle bin (stage 1 and 2) etc.

        Reply
  • Hi Salsudeen,

    Many thanks for this! It is helping us clear out many excess files we no longer require.

    I was wondering if it would be possible to target a single file rather than document library?

    Are you able to help?

    Kind Regards

    Richard

    Reply
  • Hi there, thanks a lot for the scripts. They worked fine for me on smaller document libraries. However on some big ones I receive error 429. I think this means I am being throttled. I tried waiting 4 days before trying again and it happens again. I read on https://docs.microsoft.com/en-us/sharepoint/dev/general-development/how-to-avoid-getting-throttled-or-blocked-in-sharepoint-online I should use ExecuteQueryWithIncrementalRetry instead of ExecuteQuery, but this method is not known in my libraries. I cannot quite figure out how I use this extension method in a static class and call it in the script. Any idea how and whether this will be the solution to my issue?

    Reply
    • Would love to know the answer to this too. Thanks to the OP for all this information, its an incredible help.

      Reply
  • I´m struggling with Point 2. Would it be possible to get help with it?
    The part with Sitecollection Admin i get but i cant get it work with the deletion of the version history.

    Reply
  • Hi , I am using Keep last 5 version script . I have large site with more then 100000 files I need to filter modified day Gr 365 days and exclude Jpg ,JPGE files. Can you please help

    Reply
    • Use:
      $ListItems = Get-PnPListItem -List “Branding” -PageSize 2000 | Where {$_.FileSystemObjectType -eq “File” -and $_.FieldValues.Modified -lt (Get-Date).AddDays(-365) -and $_.FieldValues.File_x0020_Type -in (“jpg”,”jpeg”)}

      Reply
  • Hi Salaudeen,

    Any chance the “Keep five versions” script can be updated to loop through all libraries in a site?

    Thanks!

    Reply
  • ‘Keep Last Five Versions and Delete the Rest’

    Hi Salaudeen,

    Can this script above be updated to cycle through all libraries in a site? Thanks!

    Reply
  • Hi Salaudeen, the script works perfect, but the deleted versions are not showing in the recycle bin or the second stage recycle bin and the storage has not been freed up. Where can I find the deleted items so that I can free up the space?

    Reply
    • The delete method permanently deletes the object without sending it to the recycle bin. Use RecycleByID or RecycleByLabel methods to send it to recycle bin. SharePoint Online stores only the Delta of different versions on specific file types, and it takes a while for storage recalculations.

      Reply
  • Hi Salaudeen
    Works perfectly 🙂
    I have a question
    Is it possible to add a session that looks when the files was last modified and delete all history version for files that haven’t been modified the last 90 days ?

    Reply
    • Use: $ListItems = Get-PnPListItem -List $ListName -PageSize 2000 | Where {$_.FileSystemObjectType -eq “File” -and $_.FieldValues.Modified -lt (Get-Date).AddDays(-90)}

      Reply
  • Hello Salaudeen,

    thank you very much for the script. It has already helped me a lot to delete the old file versions (document library) within a single site collection (SharePoint Online). For it to work, it was necessary to add an extra Site Administrator account to the site and use those credentials for the script.

    I have run the script (case 3; keep 5 versions) on a test basis for a single site.
    https://example.sharepoint.com/teams/AAA

    Is there a way (via loop) to delete versions through all sites in a tenant?
    /teams/xxx
    /sites/xxx
    Using a sharepoint admin account (or global admin) without adding a separate site admin account to each individual team site (collection)?

    Supplemental question:
    After deleting the old versions on the test site (../teams/AAA), the SharePoint Online Admin Center does not show any reduction in memory usage.
    Is there a time delay here?

    Thanks for your help
    Greetings Tom

    Reply
    • 1. Even if you are a Global Admin, You must add your account as site collection Admin to each site in SharePoint Online, As there is no Web Application Policies in SharePoint Online.
      2. You can wrap this script inside a function and call the function for each site in your tenant.
      3. Yes! There is a time delay in recalculating the disk space!

      Reply
  • Accomplished my above request and have managed to cleanup most of our files. One File has 8000 versions and we get this error when when trying to clean it up: The request message is too big. The server does not allow messages larger than 2097152 and it errors out. How can you get it to work on a large set of versions.

    Also we were running into the time out issue. It cleans ups files but not all of them. We ended up just rerunning it until it was down to 100 versions.

    Reply
    • Yes! Larger requests may end up with timeout and related issues. You can mitigate by calling $Ctx.ExecuteQuery right after the operation such as: $Versions[0].DeleteObject()

      Reply
  • What if you have a CSV file with the Site Names and Library Names that have files over the limit. Can you read the sites from a CSV file?

    Reply
  • Hi, I’m running ‘PowerShell to Clear Previous Versions by Folder by Folder’

    Worked fine in my test environment of one folder level, but doesn’t run in my live environments with up to 20 folders depth.

    Could you let me know how many folders deep the script runs and if it can be adapted to run for all files and folders in a document library.

    Other than that, great script. Something Microsoft should have done !!!

    Reply
  • Hi, I’m running ‘PowerShell to Clear Previous Versions by Folder by Folder’

    Worked fine in my test environment of one folder level, but doesn’t run in my live environments with up to 20 folders depth.

    Could you let me know how many folders deep the script runs and if it can be adapted to run for all files and folders in a document library.

    Other than that, great script. Something Microsoft should have done !!!

    Reply
  • I am using a modified version of Keep Last Five Versions and Delete the Rest Script and its fantastic, my only problem is when the versions are large >100 as an example I get a timeout on the $Ctx.ExecuteQuery()

    Deleting Version: 2.137

    Exception calling “ExecuteQuery” with “0” argument(s): “The operation has timed out”

    I attempted to extend the time out by $Ctx.RequestTimeOut = 10000 or $Ctx.RequestTimeOut = 0 but the error still happens. Is there a way to execute them as batches?

    Reply
    • Try: $Ctx.RequestTimeout = [System.Threading.Timeout]::Infinite or call $Ctx.ExecuteQuery() after each Delete operation!

      Reply
    • Thanks very much for those options, I going to push my luck here.

      The request timeout didn’t work, I still get the same error. I am invoking it directly after this line 22 $Ctx.ExecuteQuery().

      If I try the other approach to run $Ctx.ExecuteQuery() inside here
      {
      write-host -f Cyan “`t Deleting Version:” $Versions[0].VersionLabel
      $Versions[0].DeleteObject()
      $Ctx.ExecuteQuery()

      }
      It doesn’t find the array item I am trying to remove and states that $Versions[0] is null.

      Am I missing something?

      Reply
    • Exception calling “ExecuteQuery” with “0” argument(s): “Cannot invoke method or retrieve property from null object. Object returned by the following call stack is null. “””

      is the exact error.

      Reply
  • Worked perfectly. Thank you!

    Reply
  • This comment has been removed by the author.

    Reply
  • Hi, can you just delete all versions but drop them into the recycle bin? DeleteAll permanently deletes them.

    Reply
  • I love most all your articles; however, this is one that did not work for me…at all. I had to enumerate through each version and $Version.DeleteObject()

    Received errors every time I used $Version.DeleteAll() [Method invocation failed because [Microsoft.SharePoint.Client.ListItemVersion] does not contain a method named ‘DeleteAll’]

    Reply
    • Well, Versioning features were added to PowerShell CSOM’s later build. I would suggest to update the PnP PowerShell module once and give it a try!
      Update-Module SharePointPnPPowerShellOnline

      Reply
    • That’s what I thought, too. I updated the module, but still nothing.

      I think this one’s a no-go for me, my friend. I still very much love the site – use it weekly!

      Thank you.

      Reply
    • The Version Collection object has DeleteAll(), But individual version has only DeleteObject() method!

      Reply
  • This comment has been removed by the author.

    Reply
  • Thank you for these!

    When using “Keep Last Five Versions and Delete the Rest” is there a way to specify the exact sub folder in a library? For example: .sharepoint.com/sites/marketing/documents/proposals/2019

    Reply
    • Use this line to get all files from a given folder:
      $ListItems = Get-PnPListItem -List $ListName -FolderServerRelativeUrl $FolderServerRelativeURL -PageSize 2000 | Where {$_.FileSystemObjectType -eq “File”}

      Reply
  • Hi this works a treat now you have done a great job on this thank you so much

    Reply
  • Hi there

    I ran the script but I get this message now

    Get-PnPListItem : The attempted operation is prohibited because it exceeds the list view threshold enforced by the administrator.

    Regards

    Eric

    Reply
  • I am getting the following errors, any idea?
    Exception calling “ExecuteQuery” with “0” argument(s): “Cannot invoke method or retrieve property from null object.
    Object returned by the following call stack is null. “File
    “”
    At line:10 char:5
    + $Ctx.ExecuteQuery()
    + ~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : ServerException

    Reply
    • Hey, I´ve got exactly the same problem. When I echo the $ctx variable I can see that the values for Versions and displayname are Null. Any way to fix that? :/

      Reply
      • When the $Ctx is null, It indicates the connection was not successful to SharePoint!

        Reply

Leave a Reply

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