Skip to main content

Recursively remove a folder from OneDrive with PowerShell

· 2 min read

Did you know, when you have a retention policy configured for OneDrive in Microsoft 365 you lose the ability to recursively delete folders. The OneDrive client often handles this by recursing through the folder tree to remove the online copies but sometimes that doesn't work and in those cases you can end up stuck with a folder tree that you would have to manually recurse to remove the offending folders by first emptying them entirely before OneDrive will let you delete them.

Well that's never going to happen ;-)

Enter PowerShell.

Required Modules

You'll need the PnP.PowerShell module for this script. Install with Install-Module 'PnP.PowerShell'

The script

Remove-OneDriveFolderRecursively.ps1
[CmdletBinding()]
param (
# OneDrive host name e.g. 'https://microsoft-my.sharepoint.com'
[Parameter(Mandatory)]
[String]$OneDriveHost,
# Site path e.g. '/personal/satya_nadella_microsoft_com' must start with '/'.
[Parameter(Mandatory)]
[String]$SitePath,
# Folder path e.g. '/Documents/Documents/PowerShell/Modules' must start with '/'.
[String]$FolderPath
)

# Setup some configuration variables.
$SiteURL = $OneDriveHost + $SitePath
$FolderSiteRelativeURL = $SitePath + $FolderPath

# Connect to the site with the PnP.PowerShell module.
Connect-PnPOnline -Url $SiteURL -Interactive
$Web = Get-PnPWeb
$Folder = Get-PnPFolder -Url $FolderSiteRelativeURL

# Function to recursively remove files and folders from the path given.
Function Clear-PnPFolder([Microsoft.SharePoint.Client.Folder]$Folder) {
$InformationPreference = 'Continue'
If ($Web.ServerRelativeURL -eq '/') {
$FolderSiteRelativeURL = $Folder.ServerRelativeUrl
} Else {
$FolderSiteRelativeURL = $Folder.ServerRelativeUrl.Replace($Web.ServerRelativeURL, [string]::Empty)
}
# First remove all files in the folder.
$Files = Get-PnPFolderItem -FolderSiteRelativeUrl $FolderSiteRelativeURL -ItemType File
ForEach ($File in $Files) {
# Delete the file.
Remove-PnPFile -ServerRelativeUrl $File.ServerRelativeURL -Force -Recycle
Write-Information ("Deleted File: '{0}' at '{1}'" -f $File.Name, $File.ServerRelativeURL)
}
# Second loop through sub folders and remove them - unless they are "special" or "hidden" folders.
$SubFolders = Get-PnPFolderItem -FolderSiteRelativeUrl $FolderSiteRelativeURL -ItemType Folder
Foreach ($SubFolder in $SubFolders) {
If (($SubFolder.Name -ne 'Forms') -and (-Not($SubFolder.Name.StartsWith('_')))) {
# Recurse into children.
Clear-PnPFolder -Folder $SubFolder
# Finally delete the now empty folder.
Remove-PnPFolder -Name $SubFolder.Name -Folder $Site + $FolderSiteRelativeURL -Force -Recycle
Write-Information ("Deleted Folder: '{0}' at '{1}'" -f $SubFolder.Name, $SubFolder.ServerRelativeURL)
}
}
$InformationPreference = 'SilentlyContinue'
}
# Call the function to empty folder if it exists.
if ($null -ne $Folder) {
Clear-PnPFolder -Folder $Folder
} Else {
Write-Error ("Folder '{0}' not found" -f $FolderSiteRelativeURL)
}

Invoking the script

The script is looking for three parameters, an example invocation to remove a synced "Documents/PowerShell/Modules" folder in Satya Nadella's OneDrive would be:

Double the Documents

You'll notice below that the /Documents folder in the path is doubled. This is because the first folder in the OneDrive path is always /Documents then your path starts. In this example we're removing the /Documents/PowerShell/Modules folder.

Remove-OneDriveFolderRecursively -OneDriveHost 'https://microsoft-my.sharepoint.com' -SitePath '/personal/satya_natella_microsoft_com' -FolderPath '/Documents/Documents/PowerShell/Modules'

Hope this helps!

This post was inspired by a script posted on Microsoft's TechCommunity here...