Send items to second-stage SharePoint recycle bin

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

Leave a Reply