Entra / Microsoft 365 · SharePoint & OneDrive
Report files spo site
Generate a report of files in a SharePoint Online site using Microsoft Graph APIs.
Connect & set up
Run these once per session. All scopes are read-only unless the script makes changes.
Connect-MgGraph -Scopes Sites.Read.All -NoWelcome
Run it
The main script. Copy it, or download the .ps1 and run it from your console.
function UnpackFilesRecursively {# Unpack set of items (files and folders)param ([parameter(Mandatory = $true)]$Items, # Items to unpack[parameter(Mandatory = $true)]$SiteUri, # Base site URI[parameter(Mandatory = $true)]$FolderPath, # Folder path[parameter(Mandatory = $true)]$SiteFiles,[parameter(Mandatory = $false)][bool]$IsNextLink)# Find sub-folders that we need to check for files$Folders = $Items.Value | Where-Object {$_.Folder.ChildCount -gt 0 }# And any files in the folder$Files = $Items.Value | Where-Object {$null -eq $_.Folder.ChildCount}$before = $SiteFiles.count# Report the filesForEach ($D in $Files) {$FileSize = FormatFileSize $D.Size$ReportLine = [PSCustomObject] @{FileName = $D.NameFolder = $FolderPathAuthor = $D.createdby.user.displaynameCreated = $D.createdDateTimeModified = $D.lastModifiedDateTimeSize = $FileSizeUri = $D.WebUrl }$SiteFiles.Add($ReportLine)} # End If$NextLink = $Items."@odata.nextLink"$Uri = $Items."@odata.nextLink"While ($NextLink) {$MoreData = Invoke-MgGraphRequest -Uri $Uri -Method GetUnpackFilesRecursively -Items $MoreData -SiteUri $SiteUri -FolderPath $FolderPath -SiteFiles $SiteFiles -IsNextLink $true$NextLink = $MoreData."@odata.nextLink"$Uri = $MoreData."@odata.nextLink"} # End While$Count = $SiteFiles.count - $beforeif (-Not $IsNextLink) {Write-Host " $FolderPath ($count)"}# Report the files in each sub-folderForEach ($Folder in $Folders) {$NewFolderPath = $FolderPath + "/" + $Folder.Name$Uri = $SiteUri + "/" + $Folder.parentReference.path + "/" + $Folder.Name + ":/children"$SubFolderData = Invoke-MgGraphRequest -Uri $Uri -Method GetUnpackFilesRecursively -Items $SubFolderData -SiteUri $SiteUri -FolderPath $NewFolderPath -SiteFiles $SiteFiles -IsNextLink $IsNextLink} # End Foreach Folders}function FormatFileSize {# Format File Size nicelyparam ([parameter(Mandatory = $true)]$InFileSize)If ($InFileSize -lt 1KB) { # Format the size of a document$FileSize = $InFileSize.ToString() + " B" }ElseIf ($InFileSize -lt 1MB) {$FileSize = $InFileSize / 1KB$FileSize = ("{0:n2}" -f $FileSize) + " KB"}Elseif ($InFileSize -lt 1GB) {$FileSize = $InFileSize / 1MB$FileSize = ("{0:n2}" -f $FileSize) + " MB" }Elseif ($InFileSize -ge 1GB) {$FileSize = $InFileSize / 1GB$FileSize = ("{0:n2}" -f $FileSize) + " GB" }Return $FileSize}# Connect to the Microsoft Graph with the permission to read sitesDisconnect-MgGraph | Out-Null # Make sure that we sign out of existing sessionsConnect-MgGraph -Scopes Sites.Read.All -NoWelcomeWrite-Host "Looking for matching sites..."$Uri = 'https://graph.microsoft.com/v1.0/sites?search="' + $SearchSite + '"'[array]$Sites = Invoke-MgGraphRequest -Uri $uri -Method Get$Sites = $Sites.Value$SiteCount = $Sites.CountIf (!($Sites)) { # Nothing foundWrite-Host "No matching sites found - exiting"; break }If ($SiteCount -eq 1) { # Only one site found - go ahead$Site = $Sites$SiteName = $Site.DisplayNameWrite-Host "Found site to process:" $SiteName} Elseif ($SiteCount -gt 1) { # More than one site found. Ask which to useClear-Host; Write-Host "More than one matching site was found. We need you to select a site to report."; [int]$i=1Write-Host " "ForEach ($SiteOption in $Sites) {Write-Host ("{0}: {1} ({2})" -f $i, $SiteOption.DisplayName, $SiteOption.Name); $i++}Write-Host ""[Int]$Answer = Read-Host "Enter the number of the site to use"If (($Answer -gt 0) -and ($Answer -le $i)) {[int]$Si = ($Answer-1)$SiteName = $Sites[$Si].DisplayNameWrite-Host "OK. Selected site is" $Sites[$Si].DisplayName$Site = $Sites[$Si] }}If (!($Site)) {Write-Host ("Can't find the {0} site - script exiting" -f $Uri) ; break}# Get Drives in the siteWrite-Host ("Checking for document libraries in the {0} site" -f $Site.DisplayName)$Uri = "https://graph.microsoft.com/v1.0/sites/$($Site.Id)/drives"[array]$Drives = Invoke-MgGraphRequest -Uri $Uri -Method Get$Drives = $Drives.ValueIf (!($Drives)) { # Nothing foundWrite-Host "No matching drives found - exiting"; break }If ($Drives.Count -eq 1) { # Only one drive found - go ahead$Drive = $Drives$DriveName = $Drive.NameWrite-Host "Found drive to process:" $DriveName} Elseif ($Drives.Count -gt 1) { # More than one drive found. Ask which to useClear-Host; Write-Host "More than one drive found in site. We need you to select a drive to report."; [int]$i=1Write-Host " "ForEach ($DriveOption in $Drives) {Write-Host ("{0}: {1}" -f $i, $DriveOption.Name); $i++}Write-Host ""[Int]$Answer = Read-Host "Enter the number of the drive to use"If (($Answer -gt 0) -and ($Answer -le $i)) {[int]$Si = ($Answer-1)$DriveName = $Drives[$Si].NameWrite-Host "OK. Selected drive is" $Drives[$Si].Name$Drive = $Drives[$Si] }}If (!($Drive)) {Write-Host ("Can't find the {0} drive - script exiting" -f $Uri) ; break}# Use the selected drive$DocumentLibrary = $Drive$SiteUri = "https://graph.microsoft.com/v1.0/sites/$($Site.Id)"$Uri = "$SiteUri/drives/$($DocumentLibrary.Id)/root/children"# Create output list$SiteFiles = [System.Collections.Generic.List[Object]]::new()Write-Host "Reading from document library..."# Get Items in document library[array]$Items = Invoke-MgGraphRequest -Uri $Uri -Method GetUnpackFilesRecursively -Items $Items -SiteUri $SiteUri -FolderPath $DocumentLibrary.Name -SiteFiles $SiteFilesWrite-Host ("Total files found {0}" -f $SiteFiles.Count)$SiteFiles | Out-GridView
Attribution
Author
Office365itpros