List Every List and Library in a SharePoint Site with PowerShell
What you are looking for is the fast way to list what is inside your SharePoint site – what lists and libraries exist there and how many and large they are. It looks like you can do that in one go. But the most straightforward way is misleading you in two points, while the way most people calculate sizes is slow. Tested with PnP.PowerShell 2.12.0 against real site.
Get-PnPList returns far more than you asked for
$all = Get-PnPList
$all.Count
Total lists returned : 19
Hidden : 11
Visible : 8
Nineteen, out of which I made four. And the remaining seventeen are the internal structures on which SharePoint works: Solution Gallery, TaxonomyHiddenList, Theme Gallery, User Information List and so on. Out of the seventeen, eleven are invisible.
So the first step would be filtration. We are interested in getting only visible lists and we need to make sure that we don’t consider galleries and form template stores. There are two base templates for that purpose, 100 for list, 101 for document library.
Get-PnPList |
Where-Object { -not $_.Hidden -and $_.BaseTemplate -in @(100, 101) } |
Select-Object Title,
@{n='Kind'; e={ if ($_.BaseTemplate -eq 101) { 'Library' } else { 'List' } }},
ItemCount,
@{n='LastChanged'; e={ $_.LastItemUserModifiedDate }} |
Sort-Object Kind, Title
Title Kind ItemCount LastChanged
----- ---- --------- -----------
Agent Knowledge Library 4 22/07/2026
Project Documents Library 14 22/07/2026
Departments List 4 18/07/2026
Projects List 25 22/07/2026
LastItemUserModifiedDate is worth having in there. It is the last time a person changed something, which is how you spot the libraries nobody has touched in a year.
ItemCount is not the number of files
Look at Project Documents above, ItemCount 14. But there are not fourteen documents in it. I checked:
Project Documents ItemCount : 14
Actual files : 8
Folders (also in ItemCount) : 6
ItemCount includes folders as items, too. A library containing 8 files in 6 folders has a total number of 14. And when you say to somebody “this library contains 14 documents,” then you are wrong as many times as there are folders.
To know the true number of files, you need to ask
@(Get-PnPListItem -List 'Project Documents' -PageSize 500 |
Where-Object { $_.FileSystemObjectType -eq 'File' }).Count
Same trap applies to a list with folders in it, which is rarer but does happen.
Size: the fast way and the slow way
This is where an inventory script quietly becomes an overnight job, so it is worth understanding the two approaches before you pick one.
The fast way: ask the site for its own number
Every site collection already knows how much storage it uses. One call gets it, but the call lives in the admin centre:
Connect-PnPOnline -Url "https://contoso-admin.sharepoint.com" -ClientId "..." -Interactive
$site = Get-PnPTenantSite -Identity "https://contoso.sharepoint.com/sites/Demo"
$site.StorageUsageCurrent
Fast: 1 MB in 805ms
One request, under a second, and it does not care whether the site has ten files or ten million. The catch is that it is a whole-site figure and it needs SharePoint admin. You cannot break it down per library this way, and you cannot run it as an ordinary site member.
The slow way: add up every file
If you need it per library, or you do not have admin, you sum the file sizes yourself:
$libraries = Get-PnPList | Where-Object { -not $_.Hidden -and $_.BaseTemplate -eq 101 }
foreach ($lib in $libraries) {
$bytes = 0
Get-PnPListItem -List $lib -PageSize 500 |
Where-Object { $_.FileSystemObjectType -eq 'File' } |
ForEach-Object { $bytes += [long]$_.FieldValues['File_x0020_Size'] }
[pscustomobject]@{
Library = $lib.Title
SizeMB = [math]::Round($bytes / 1MB, 2)
}
}
Library SizeMB
------- ------
Agent Knowledge 0.07
Project Documents 0.07
...
Took : 3.7s for 5 libraries
Note the field name, File_x0020_Size, with the encoded space. That is the internal name, and it will not work as “File Size”. I wrote up why that happens in finding a list’s internal column names.
The gap is unbounded, not four times
The faster method ran in 805 milliseconds while the slower one was about three-point-seven seconds which means it was almost four times slower. But the difference is not the issue since it cannot stand.
The faster method uses a single request no matter the size while the slower method requires one request per item. Five libraries with close to nothing in them will mean nothing to the process but fifty thousand documents in one library will mean fifty thousand requests, and you will measure in minutes for each library and not seconds for each site.
So in conclusion, it is easy to say that if you have an admin user account and all you need is total statistics of your sites, go for the StorageUsageCurrent method since it will be completed within one second. But when you require summing up the files of your library, know it will take more time.
.
The version I keep
Get-PnPList |
Where-Object { -not $_.Hidden -and $_.BaseTemplate -in @(100, 101) } |
Select-Object Title,
@{n='Kind'; e={ if ($_.BaseTemplate -eq 101) { 'Library' } else { 'List' } }},
@{n='Items'; e={ $_.ItemCount }},
@{n='LastChanged'; e={ $_.LastItemUserModifiedDate }} |
Sort-Object Kind, Title |
Format-Table -AutoSize
Quick, honest about what it does show, and requires no administration. It counts files in the folder total, and therefore if this is important to your task, use the FileSystemObjectType filter, and remember you are giving up speed for accuracy. ?