Bulk delete items and folders from Sharepoint document library using Powershell
Fri, Aug 10, 2018
2-minute read
I’ll cut to the chase. A lot has been written about how to handle large lists and how to handle bulk deleting things. To summarise: getting all items and iterating one by one is *not* the way to do it.
The right way to do it is to use the ProcessBatchData method on the SPWeb object.
Have done this plenty of times in C# but this time I wanted to cut straight to Powershell. A quick Google later and I found Daniel Root’s boiler plate. It properly handles checked out files as well, and deletes folders. Ideal!
I’ve made a quick tweak to check for null parameters.
param($url,$libraryName) if($null -eq $url -or $null -eq $libraryName) { write-host "Must provide params URL and LibraryName." break } $w = get-spweb $url $l = $w.Lists[$libraryName] $format = "<method><setlist Scope=`"Request`">$($l.ID)</setlist><setvar Name=`"ID`">{0}</setvar><setvar Name=`"Cmd`">Delete</setvar><setvar Name=`"owsfileref`">{1}</setvar></method>" function DeleteAllFiles($folder) { $count = $folder.Files.Count - 1 if($count -gt -1){ Write-Host "Deleting $count files..." for($i = $count; $i -gt -1; $i--){ $f = $folder.Files[$i]; if($f.CheckOutStatus -ne [Microsoft.SharePoint.SPFile+SPCheckOutStatus]::None){ $f.CheckIn("Checkin by admin"); } $f.Delete() } } } function BuildBatchDeleteCommand($items) { $sb = new-object System.Text.StringBuilder $sb.Append("< ?xml version=`"1.0`" encoding=`"UTF-8`"?><batch>") $items | %{ $item = $_ $sb.AppendFormat($format,$item.ID.ToString(),$item.File.ServerRelativeUrl.ToString()) } $sb.Append("</batch>") return $sb.ToString() } $count = $l.CheckedOutFiles.Count -1; Write-Host "Taking over $count items that have never been checked in." for($i = $count; $i -gt -1; $i--){ $f = $l.CheckedOutFiles[$i]; $f.TakeOverCheckOut() Write-Host $f.Url } Write-Host "Deleting $($l.Items.Count) items" while($l.Items.Count -gt 0){ $q = new-object "Microsoft.SharePoint.SPQuery" $q.ViewFields="<fieldref Name=`"ID`"></fieldref>" $q.ViewAttributes = "Scope=`"Recursive`"" $q.RowLimit=1000 $items = $l.GetItems($q) $cmd = BuildBatchDeleteCommand($items) Write-Host "Deleting $($items.Count) items..." $result = $w.ProcessBatchData($cmd) if ($result.Contains("ErrorText")){ break; } Write-Host "Deleted. $($l.Items.Count) items left..." } Write-Host "Deleting $count folders..." $l.Folders | %{$_.Url.ToString()} | sort -descending | %{ $folder = $_ $folder $f = $w.GetFolder($folder) $f.Files.Count $f.Delete() }