How to Set SharePoint File Versions to Never Expire Using PowerShell
The Challenge
SharePoint Online’s automatic version deletion feature is designed to help organizations manage storage by automatically removing old file versions. When you enable automatic version trimming at the tenant level, SharePoint sets expiration dates on file versions before they’re permanently deleted.
However, there are scenarios where you might want to preserve specific versions indefinitely—perhaps they contain critical information, represent important milestones, or are required for compliance purposes. This is
The Solution
Fortunately, SharePoint’s REST API provides the SetExpirationDate() method that allows you to modify or remove expiration dates on file versions. By setting the expiration date to null, you can ensure that specific versions are never automatically deleted.
Below is a PowerShell script that leverages the PnP PowerShell module and SharePoint REST API to set a file version’s expiration date to never expire.
Prerequisites
- PnP PowerShell Module: Install the PnP PowerShell module if you haven’t already:
Install-Module -Name PnP.PowerShell - Appropriate Permissions: You need sufficient permissions to manage file versions in the target SharePoint site.
The PowerShell Script to update only one version
param (
[Parameter(Mandatory = $true)]
[string]$SiteUrl,
[Parameter(Mandatory = $true)]
[string]$FileServerRelativeUrl,
[Parameter(Mandatory = $true)]
[string]$VersionLabel
)
# Connect to SharePoint site interactively
Connect-PnPOnline -Url $SiteUrl
# Step 1: Get the version ID corresponding to the version label
$encodedFileUrl = [System.Uri]::EscapeDataString($FileServerRelativeUrl)
$filterUrl = "$SiteUrl/_api/web/GetFileByServerRelativePath(DecodedUrl='$encodedFileUrl')/versions?`$filter=VersionLabel eq '$VersionLabel'&`$select=ID"
$versionResponse = Invoke-PnPSPRestMethod -Url $filterUrl -Method Get
if ($versionResponse.value.Count -eq 0) {
Write-Host "No version found with label '$VersionLabel'" -ForegroundColor Red
exit
}
$versionId = $versionResponse.value[0].ID
Write-Host "Found version ID: $versionId for label '$VersionLabel'" -ForegroundColor Green
# Step 2: Set the expiration date to null (never expire)
$expirationUrl = "$SiteUrl/_api/web/GetFileByServerRelativePath(DecodedUrl='$encodedFileUrl')/versions($versionId)/SetExpirationDate()"
Write-Host "Calling: $expirationUrl" -ForegroundColor Yellow
Invoke-PnPSPRestMethod -Url $expirationUrl -Method Post -Content '{ "expirationDate": null }'
Write-Host "Expiration date set to never expire for version $VersionLabel." -ForegroundColor Cyan
How to Use the Script
Save the Script: Save the script to a file, for example,
Set-FileVersionNoExpiration.ps1.Run the Script: Execute the script with the required parameters:
.\Set-FileVersionNoExpiration.ps1 -SiteUrl "https://contoso.sharepoint.com/sites/YourSite" ` -FileServerRelativeUrl "/sites/YourSite/Shared Documents/YourFile.docx" ` -VersionLabel "1.0"Parameters Explained:
- SiteUrl: The full URL of your SharePoint site
- FileServerRelativeUrl: The server-relative path to the file (e.g.,
/sites/YourSite/Shared Documents/document.docx) - VersionLabel: The version label you want to preserve (e.g.,
1.0,2.5,3.0)
How It Works
Connection: The script connects to the SharePoint site using interactive authentication.
Version Lookup: It queries the SharePoint REST API to find the internal version ID that corresponds to the specified version label.
Expiration Removal: Once the version ID is found, the script calls the
SetExpirationDate()endpoint with anullvalue, effectively removing the expiration date and preventing automatic deletion.
Key Considerations
- Version Labels: Make sure you use the correct version label format (e.g.,
1.0,2.0, not just1or2). - Server-Relative URL: The file path must be server-relative, not site-relative. Include the full path from the root.
- Permissions: You must have edit permissions on the file and its versions.
- Bulk Operations: If you need to process multiple versions or files, consider wrapping this logic in a loop or creating a CSV-based batch script.
The PowerShell Script to update only major versions to not expire
param (
[Parameter(Mandatory = $true)]
[string]$SiteUrl,
[Parameter(Mandatory = $true)]
[string]$LibraryName
)
# Connect interactively to SharePoint
Connect-PnPOnline -Url $SiteUrl -Interactive
# Get all files in the specified document library
Write-Host "Fetching files from library: $LibraryName ..." -ForegroundColor Cyan
$files = Get-PnPListItem -List $LibraryName -PageSize 1000 -Fields "FileRef", "FileLeafRef" | Where-Object { $_.FieldValues.FileRef -ne $null }
if ($files.Count -eq 0) {
Write-Host "No files found in library '$LibraryName'." -ForegroundColor Yellow
exit
}
foreach ($file in $files) {
$fileRef = $file.FieldValues.FileRef
$encodedFileUrl = [System.Uri]::EscapeDataString($fileRef)
Write-Host "`nProcessing file: $fileRef" -ForegroundColor White
# Get all versions of the current file
$versionsUrl = "/_api/web/GetFileByServerRelativePath(DecodedUrl='$encodedFileUrl')/versions?$select=ID,VersionLabel"
$versionsResponse = Invoke-PnPSPRestMethod -Url $versionsUrl -Method Get
if ($versionsResponse.value.Count -eq 0) {
Write-Host " No versions found for file." -ForegroundColor Yellow
continue
}
# Filter only major versions (X.0)
$majorVersions = $versionsResponse.value | Where-Object {
$_.VersionLabel -match '^\d+\.0$'
}
if ($majorVersions.Count -eq 0) {
Write-Host " No major versions found." -ForegroundColor DarkYellow
continue
}
foreach ($version in $majorVersions) {
$versionId = $version.ID
$versionLabel = $version.VersionLabel
$setExpirationUrl = "/_api/web/GetFileByServerRelativePath(DecodedUrl='$encodedFileUrl')/versions($versionId)/SetExpirationDate()"
# Call REST API to set expiration
Invoke-PnPSPRestMethod -Method Post -Url $setExpirationUrl -Content '{ "expirationDate": null }'
Write-Host " ✅ Retained major version $versionLabel (ID $versionId) for file." -ForegroundColor Green
}
}
Conclusion
While SharePoint’s automatic version trimming helps manage storage, having the ability to preserve critical versions is essential for many organizations. This PowerShell script provides a straightforward way to remove expiration dates from specific file versions, ensuring they’re retained indefinitely.
By leveraging the SharePoint REST API through PnP PowerShell, you gain fine-grained control over version management that goes beyond what’s available in the standard cmdlets.