Bulk Restore Files from 365 Sharepoint Recycle Bin Using Powershell
NEED IT SUPPORT? VISIT SUPPORT.ITOFUS.COM AND OPEN A TICKET!
SOFTWARE
Install SharePoint Online Management Shell
REQUIREMENTS
Install-Module Microsoft.Online.SharePoint.PowerShell
Install-Module SharePointPnPPowerShellOnline
URL ------------> MUST BE ADJUSTED
$OrgAdminURL = "https://domain-admin.sharepoint.com"
$SiteURL = "https://domain.sharepoint.com/sites/SiteName/"
LOGIN
Connect-SPOService -Url $OrgAdminURL
Connect-PnPOnline -Url $SiteURL -UseWebLogin
PATHS ------------> MUST BE ADJUSTED
$S1Path = "C:\Stage1Restore.csv"
$S2Path = "C:\Stage2Restore.csv"
DATES
$Today = Get-Date -DisplayHint Date #DO NOT CHANGE
$From = $Today.date.AddDays(-6) # ------------> MUST BE ADJUSTED
$To = $Today.date.AddDays(-0) # ------------> MUST BE ADJUSTED. -0 IS TODAY
USER
$DeletedUser = "user@domain.com" # ------------> MUST BE ADJUSTED TO THE USER EMAIL WHO DELETED THE DATA
FILES LIMIT
$MaxFiles = 500000 #------------> MUST BE ADJUSTED BETWEEN 0 AND 500000
###################################################################
#OBTAIN DATA
###################################################################
Echo "Obtaining Data. Please Wait ... This may take a few hours"
$DeletedItems1 = Get-PnPRecycleBinItem -firststage -RowLimit $MaxFiles | Where-Object {($_.DeletedDate -ge $From -and $_.DeletedDate -le $To) -and ($_.DeletedByEmail -eq $DeletedUser)}
$DeletedItems2 = Get-PnPRecycleBinItem -secondstage -RowLimit $MaxFiles | Where-Object {($_.DeletedDate -ge $From -and $_.DeletedDate -le $To) -and ($_.DeletedByEmail -eq $DeletedUser)}
###################################################################
#DATA PREVIEW TO BE RESTORED (STAGE 1)
###################################################################
Echo "Stage 1 Preview"
$DeletedItems1 | Select Title, DeletedByName, DeletedDate | Format-table
###################################################################
###################################################################
#DATA PREVIEW TO BE RESTORED (STAGE 2)
###################################################################
Echo "Stage 2 Preview"
$DeletedItems2 | Select Title, DeletedByName, DeletedDate | Format-table
###################################################################
###################################################################
#EXPORT STAGE 1 DATA INFO TO CSV
###################################################################
Echo "Stage 1 CSV Export. Please Wait ... This may take a few hours"
$Output1 = @()
$DeletedItems1 | ForEach-Object {
$Item = $PSItem
$Obj = "" | Select-Object Title, AuthorEmail, AuthorName, DeletedBy, DeletedByEmail, DeletedDate, Directory, ID, ItemState, ItemType, LeafName, Size
$Obj.Title = $Item.Title
$Obj.AuthorEmail = $Item.AuthorEmail
$Obj.AuthorName = $Item.AuthorName
$Obj.DeletedBy = $Item.DeletedByName
$Obj.DeletedByEmail = $Item.DeletedByEmail
$Obj.DeletedDate = $Item.DeletedDate
$Obj.Directory = $Item.DirName
$Obj.ID = $Item.ID
$Obj.ItemState = $Item.ItemState
$Obj.ItemType = $Item.ItemType
$Obj.LeafName = $Item.LeafName
$Obj.Size = $Item.Size
$Output1 += $Obj
}
$Output1 | Export-csv $S1Path -NoTypeInformation
###################################################################
###################################################################
#EXPORT STAGE 2 DATA INFO TO CSV
###################################################################
Echo "Stage 2 CSV Export. Please Wait ... This may take a few hours"
$Output2 = @()
$DeletedItems2 | ForEach-Object {
$Item = $PSItem
$Obj = "" | Select-Object Title, AuthorEmail, AuthorName, DeletedBy, DeletedByEmail, DeletedDate, Directory, ID, ItemState, ItemType, LeafName, Size
$Obj.Title = $Item.Title
$Obj.AuthorEmail = $Item.AuthorEmail
$Obj.AuthorName = $Item.AuthorName
$Obj.DeletedBy = $Item.DeletedByName
$Obj.DeletedByEmail = $Item.DeletedByEmail
$Obj.DeletedDate = $Item.DeletedDate
$Obj.Directory = $Item.DirName
$Obj.ID = $Item.ID
$Obj.ItemState = $Item.ItemState
$Obj.ItemType = $Item.ItemType
$Obj.LeafName = $Item.LeafName
$Obj.Size = $Item.Size
$Output2 += $Obj
}
$Output2 | Export-csv $S2Path -NoTypeInformation
###################################################################
###################################################################
#RESTORE DATA
###################################################################
Function Restore-RecycleBinItem {
param(
[Parameter(Mandatory)]
[String]
$Id
)
$APICall = $SiteURL + "/_api/site/RecycleBin/RestoreByIds"
$Body = "{""ids"":[""$Id""]}"
Write-Verbose "Performing API Call to Restore Item from Recycle Bin"
try {
Invoke-PnPSPRestMethod -Method Post -Url $APICall -Content $Body | Out-Null
}
catch {
Write-Error "Unable to Restore ID {$Id}"
}
}
$ErrorActionPreference = 'Continue'
$InformationPreference = 'Continue'
Echo "Stage 1 Data Restoring. Please Wait ... This may take a few hours"
@($(Import-Csv -Path:"$S1Path")).ForEach({
$csv = $PSItem
Write-Information -MessageData:"Restoring Stage 1 Item $($csv.Title)"
Restore-RecycleBinItem -Id $($csv.ID)
})
Echo "Stage 2 Data Restoring. Please Wait ... This may take a few hours"
#STAGE 2 RESTORE IS ON BETA TESTING
@($(Import-Csv -Path:"$S2Path")).ForEach({
$csv2 = $PSItem
Write-Information -MessageData:"Restoring Stage 2 Item $($csv2.Title)"
Restore-RecycleBinItem -Id $($csv2.ID)
})
###################################################################