A client recently had a case where a migration of tens of thousands of documents into a document library failed, and they wanted to delete everything and start over. It turns out there is no easy ‘Delete Everything’ button or API call in SharePoint. Instead, I came up with this gem to fairly quickly check in any ‘orphan’ files, delete a few thousand items in batches of 1000, and then delete all folders:
param($url,$libraryName)
$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`" />"    
    $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()
}
No comments:
Post a Comment