When a document or folder is deleted in SharePoint, it goes to the first-stage (site) recycle bin. After some time, it is moved to the second-stage recycle bin. And it stays there for another period before being completely deleted.
If you need to delete a very large number of documents in SharePoint, you may consider sending the items straight to the second-level recycle bin. This will prevent “flooding” the first-stage recycle bin with items, which would make the recycle bin hard to use for manually restoring deleted items.
This can be easily done with a few lines of PnP PowerShell.
First we need to delete the item and send it to the first-level recycle bin. We then query the recycle bin and retrieve the item with a DirName and Title that match the item previously deleted.
# Use Get-PnPListItem to retrieve the item(s) to delete
Remove-PnPListItem -List $DocLib -Identity $Item["ID"] -Recycle -Force
$path = $Item["FileRef"].substring(1) # remove first '/' from path as recycle bin items don't start with '/'
$path = $path.substring(0, $path.LastIndexOf('/')) # remove folder name and last '/'
$deletedItem = Get-PnPRecycleBinItem -FirstStage -RowLimit 1 | Where-Object { $_.DirName -Eq $path -and $_.Title -Eq $Item["FileLeafRef"]}
Move-PnpRecycleBinItem -Identity "$($deletedItem.Id)" -Force
Sample use case: Send all empty folders and files to second-stage recycle bin
The following script is an extension of the script that Veronique Lengelle published on her blog. The original script was to find empty folders and documents on a site. I have extended it to send all empty folders and files to the second-stage recycle bin. Finally, we move that item to the second-level recycle bin.
#Connect to SPO
Connect-PnPOnline -Url https://contoso.sharepoint.com/sites/Test -UseWebLogin
#Store in variable all the document libraries in the site
$DocLibrary = Get-PnPList | Where-Object { $_.BaseTemplate -eq 101 }
$LogFile = "C:\users\$env:USERNAME\Desktop\SPOEmptyFoldersAndDocuments.csv"
$results = @()
foreach ($DocLib in $DocLibrary) {
#Get list of all folders and documents in the document library
$AllItems = Get-PnPListItem -PageSize 1000 -List $DocLib -Fields "SMTotalFileStreamSize", "Author", "ID"
#Loop through each files/folders in the document library for folder size = 0
foreach ($Item in $AllItems) {
if ((([uint64]$Item["SMTotalFileStreamSize"]) -eq 0)) {
Write-Host "Empty folder/file:" $Item["FileLeafRef"] -ForegroundColor Yellow
#Creating object to export in .csv file
$results += [pscustomobject][ordered] @{
CreatedDate = [DateTime]$Item["Created_x0020_Date"]
FileName = $Item["FileLeafRef"]
CreatedBy = $Item.FieldValues.Author.LookupValue
FilePath = $Item["FileRef"]
SizeInMB = ($Item["SMTotalFileStreamSize"] / 1MB).ToString("N")
LastModifiedBy = $Item.FieldValues.Editor.LookupValue
EditorEmail = $Item.FieldValues.Editor.Email
LastModifiedDate = [DateTime]$Item["Modified"]
}
#Remove item - send to first-level recycle bin
Remove-PnPListItem -List $DocLib -Identity $Item["ID"] -Recycle -Force
#Generate relative path in the same format as used by the recycle bin. Example: sites/Test/Shared Documents
$path = $Item["FileRef"].substring(1) # remove first '/' from path as recycle bin items don't start with '/'
$path = $path.substring(0, $path.LastIndexOf('/')) # remove folder name and last '/'
#Get previously deleted item from first stage recycle bin using path and title
$deletedItem = Get-PnPRecycleBinItem -FirstStage -RowLimit 1 | Where-Object { $_.DirName -Eq $path -and $_.Title -Eq $Item["FileLeafRef"]}
#Move item to second-stage recycle bin
Move-PnpRecycleBinItem -Identity "$($deletedItem.Id)" -Force
Invoke-PnPQuery
}#end of IF statement
}
}
$results | Export-Csv -Path $LogFile -NoTypeInformation