List all lists and file count using CLI for Microsoft 365

List all lists and file count using CLI for Microsoft 365 header image

Migrations can always be a tricky thing. In most cases you want to produce some form of reporting to confirm migration results. Or sometimes just to prove you have done whatever you promised to do. Luckily, you are not the only one. As Jasper Oosterveld had a similar issue. Making sure the numbers add up, he was looking for a script to report how many files each folder hold during a migration.

CLI for Microsoft

I have been a maintainer of the CLI for Microsoft 365 for a while now, during that time I wrote a few scripts for my own migrations, but this scenario was not in our samples yet. So, I took the challenge and wanted to write a sample script that would achieve the desired results. As the CLI already provides commands for working with folders and files the script is straight forward. We need to get all folders using m365 spo folder list. Then use m365 spo folder get for more details like the item count. Finally, we use a recursive function to loop through all subfolders.


Given the fact that we wanted to use this file in a reporting scenario we choose to expose all information as a CSV file. CSV files can be used for further processing, and you could use them in Excel if you want to combine different reports. To clarify and give some more information in the report we also listed whether the itemcount is found on a (sub)folder or a list.

Report all Lists and their file counts in a Site Collection

The final script contains some logic to make sure we are logged in properly. And since we do not know how many folders require processing some output is written in the console to track the progress. This all results in the following script.

$fileExportPath = "<PUTYOURPATHHERE.csv>"

$m365Status = m365 status

if ($m365Status -eq "Logged Out") {
  # Connection to Microsoft 365
  m365 login

[System.Collections.ArrayList]$results = @()

function Get-Folders($webUrl, $folderUrl) {
    $folders = m365 spo folder list -u $webUrl --parentFolderUrl $folderUrl -o json | ConvertFrom-Json

    foreach($folder in $folders){
        $folderStats = m365 spo folder get -u $webUrl --folderUrl $folder.ServerRelativeUrl -o json | ConvertFrom-Json

        Write-Output "Processing folder: $($folder.ServerRelativeUrl);"
        [void]$results.Add([pscustomobject]@{ Url = $folder.ServerRelativeUrl; ItemCount = $folderStats.ItemCount; Type = "Folder"; })

        Get-Folders $webUrl $folder.ServerRelativeUrl

$allLists = m365 spo list list -u $siteUrl -o json | ConvertFrom-Json

foreach($list in $allLists){
    if($false -eq $list.Hidden -and $list.BaseTemplate -eq "101") {
        Write-Output "Processing $($list.Url)"
        [void]$results.Add([PSCustomObject]@{ Url = $list.Url; ItemCount = $list.ItemCount; Type = "List";})

        Get-Folders $siteUrl $list.Url

$results | Export-Csv -Path $fileExportPath -NoTypeInformation

Let me know if it helps you during your migration efforts, and if you have any questions do not hesitate to reach out!

Loading comments…