Search-RecycleBin
This PnP PowerShell script searches a SharePoint Online site collection's recycle bin — both first-stage (user-deleted) and second-stage (site collection recycle bin) — for items whose name, title, or original path contains a given search string. It's a quicker way to confirm whether a specific file or folder was deleted, when, and by whom, than paging through the recycle bin UI, and it works right up until the 93-day retention window closes the second-stage bin out for good. For background on why that window matters and what it doesn't cover, see SharePoint and OneDrive: Archive vs Backup — What Each Solves (and What They Don't).
Purpose
- Connects interactively to a single SharePoint Online site via PnP PowerShell
- Retrieves every item currently in that site's recycle bin — first- and second-stage combined — via
Get-PnPRecycleBinItem - Filters results with a case-insensitive wildcard match against item name, title, and original folder path
- Prints match counts and a table sorted by deletion date, most recent first
- Optionally exports the full match set to a timestamped CSV
- Includes a commented-out restore step to recover matched items once you've confirmed which ones are needed
Scope
- Searches one site collection at a time — there's no tenant-wide recycle bin search across multiple sites in a single run
- Only finds items still within the recycle bin's retention window; once an item has passed through both recycle bin stages or the bin has been manually emptied, it's gone and this script can't find it
- Matching is a wildcard against name, title, and path — not a content search, so it won't find a deleted file based on what was inside it
- The restore step is commented out by default so a search can't accidentally restore anything; it has to be deliberately uncommented and re-run
Prerequisites
- PnP.PowerShell module installed
- Site Collection Administrator (or tenant admin) permissions on the target site —
Get-PnPRecycleBinItemrequires access to that site's recycle bin - An Azure AD app registration client ID for interactive login, or leave
$ClientIdblank to use PnP PowerShell's default multi-tenant app
PowerShell Script
# ============================================================
# Search-RecycleBin.ps1
# Searches a SharePoint Online site collection recycle bin
# (first and second stage) for items whose name, title, or
# original path contains a given string.
# ============================================================
<#
.SYNOPSIS
Searches a SharePoint Online site collection recycle bin (first and second stage)
for items whose name, title or original path contains a given string.
#>
# ===================== CONFIG — change these =====================
$SiteUrl = "https://tenantName.sharepoint.com/sites/siteName"
$ClientId = ""
$SearchString = "" # text to look for (case-insensitive)
$ExportCsv = $true # set to $false to skip CSV export
$CsvPath = ".\RecycleBinSearch_$(Get-Date -Format 'yyyyMMdd_HHmmss').csv"
# =================================================================
try {
Connect-PnPOnline -Url $SiteUrl -ClientId $ClientId -Interactive -ErrorAction Stop
Write-Host "Connected to $SiteUrl" -ForegroundColor Green
}
catch {
Write-Error "Failed to connect: $($_.Exception.Message)"
return
}
Write-Host "Retrieving recycle bin items (first + second stage)..." -ForegroundColor Cyan
$allItems = Get-PnPRecycleBinItem -RowLimit 999999
Write-Host "Total items in recycle bin: $($allItems.Count)" -ForegroundColor Cyan
$pattern = "*$SearchString*"
$matches = $allItems | Where-Object {
$_.LeafName -like $pattern -or
$_.Title -like $pattern -or
$_.DirName -like $pattern
}
if (-not $matches) {
Write-Host "No items found matching '$SearchString'." -ForegroundColor Yellow
Disconnect-PnPOnline
return
}
$results = $matches | Select-Object `
@{ N = 'Name'; E = { $_.LeafName } },
@{ N = 'Title'; E = { $_.Title } },
@{ N = 'OriginalPath'; E = { $_.DirName } },
@{ N = 'ItemType'; E = { $_.ItemType } },
@{ N = 'Stage'; E = { $_.ItemState } },
@{ N = 'DeletedBy'; E = { $_.DeletedByEmail } },
@{ N = 'DeletedDate'; E = { $_.DeletedDate } },
@{ N = 'SizeKB'; E = { [math]::Round($_.Size / 1KB, 1) } },
@{ N = 'Id'; E = { $_.Id } }
Write-Host "Found $($results.Count) matching item(s):" -ForegroundColor Green
$results | Sort-Object DeletedDate -Descending | Format-Table Name, OriginalPath, ItemType, Stage, DeletedBy, DeletedDate -AutoSize
if ($ExportCsv) {
$results | Export-Csv -Path $CsvPath -NoTypeInformation -Encoding UTF8
Write-Host "Exported to $CsvPath" -ForegroundColor Green
}
# ---- Optional: restore the matches (uncomment to use) ----
# $matches | ForEach-Object { Restore-PnPRecycleBinItem -Identity $_.Id -Force }
Disconnect-PnPOnline
Usage Notes
$SiteUrlis the single site collection to search — this doesn't run tenant-wide, so point it at the site you're investigating and re-run per site if needed$ClientIdis your Azure AD app registration client ID; leave it blank to use PnP PowerShell's default interactive app$SearchStringis matched case-insensitively against name, title, and original path — it's automatically wrapped in wildcards (*$SearchString*), so a partial filename or folder name is enough$ExportCsvset to$falseskips the CSV export and leaves results in the console only$CsvPathdefaults to a timestamped file in the current directory — override it to write to a shared location- The console table is sorted by
DeletedDatedescending, but the CSV export writes$resultsin its original, unsorted order — re-sort the CSV yourself if you need the same chronological order there - The restore line near the bottom is commented out by default —
Restore-PnPRecycleBinItem -Forcerestores without a confirmation prompt, so only uncomment it after confirming$matchescontains exactly the items you want back
Related
- SharePoint and OneDrive: Archive vs Backup — What Each Solves (and What They Don't) — covers the 93-day recycle bin retention window this script operates within, and why it isn't a substitute for backup