0

I have this script to loop through all site collections and all document libraries. Then list the folders in this format "Site Name >> List Name >> Folder Name":

$AdminUrl = "https://*****-admin.sharepoint.com/"
Connect-PnPOnline -Url $AdminUrl -Interactive

# SharePoint online get all site collections PowerShell
$SiteColl = Get-PnPTenantSite

# SharePoint online PowerShell iterate through all site collections
ForEach($Site in $SiteColl)
{
    Connect-PnPOnline -Url $Site.Url -Interactive
    $Webs = Get-PnPSubWeb -Recurse -IncludeRootWeb

    # Get all document libraries
    ForEach($Web in $Webs)
    {
        $DocumentLibraries = Get-PnPList -Web $Web | Where-Object {$_.BaseType -eq "DocumentLibrary" -and $_.Title -ne "Site Assets" -and $_.Hidden -eq $false}
        # Iterate through each document library
        ForEach($Library in $DocumentLibraries)
        {
            $f = Get-PnPFolder -List $Library

            ForEach($folder in $f)
            {

                Write-Host $Site.Title " --> "  $Library.Title  " --> " $folder.Name
            }
        }
    }
}

But the issue I am facing is that Get-PnPFolder -List $Library will get all the main folders and sub-folders... So how I can restrict this command to only get the main folders (first level folders) without sub-folders?

Here is the updated script:

$AdminUrl = "https://***-admin.sharepoint.com/"
Connect-PnPOnline -Url $AdminUrl -Interactive

# SharePoint online get all site collections PowerShell
$SiteColl = Get-PnPTenantSite
$csvOutput = @()

# SharePoint online PowerShell iterate through all site collections
ForEach($Site in $SiteColl)
{
    Connect-PnPOnline -Url $Site.Url -Interactive
    $Webs = Get-PnPSubWeb -Recurse -IncludeRootWeb

    # Get all document libraries
    ForEach($Web in $Webs)
    {
        $DocumentLibraries = Get-PnPList -Web $Web | Where-Object {$_.BaseType -eq "DocumentLibrary" -and $_.Title -ne "Site Assets" -and $_.Hidden -eq $false}
        # Iterate through each document library
        ForEach($Library in $DocumentLibraries)
        {
            $f = Get-PnPFolder -List $Library

            ForEach($folder in $f)
            {
                Write-Host $Site.Title " --> "  $Library.Title  " --> " $folder.Name " --> " $folder.ServerRelativeUrl
                $csvOutput +=  [PsCustomObject]@{SiteTitle = $Site.Title; LibraryTitle = $Library.Title; Folder = $folder.Name; FolderPath = $folder.ServerRelativeUrl}
            }

        }
    }
}
$csvOutput | Export-Csv -NoTypeInformation -Path "D:\export123.csv"

And the csvOutput will have values such as:

NewRoot  -->  dv  -->  test123  -->  /dv/test123
NewRoot  -->  dv  -->  P100  -->  /dv/P100
NewRoot  -->  dv  -->  WIP  -->  /dv/P100/WIP
NewRoot  -->  Site Pages  -->  Templates  -->  /SitePages/Templates
NewRoot  -->  tagggg  -->  a1  -->  /tagggg/a1
NewRoot  -->  tagggg  -->  a2  -->  /tagggg/a1/a2
NewRoot  -->  testdcdc  -->  test  -->  /testdcdc/test
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
John John
  • 1
  • 72
  • 238
  • 501
  • Capture the output with `$result = ForEach($Site in $SiteColl) {...}` and instead of `Write-Host $Site.Title " --> " $Library.Title " --> " $folder.Name` output **objects** `[PsCustomObject]@{SiteTitle = $Site.Title; LibraryTitle = $Library.Title; Folder = $folder.Name}` After that you can filter out the folders you see as 1st level with a Where-Object clause – Theo Feb 07 '23 at 14:17
  • @Theo do you have sample code please? – John John Feb 07 '23 at 14:19
  • 1
    No. I don't have that. Can you also export the folders Path (not just the Name). Please try this and show us a sample of what you have collected in variable $result. – Theo Feb 07 '23 at 14:21
  • @Theo the code i have can not differentiate first level and second level folders it treat them all the same.. so the where clause can not identify the main folders – John John Feb 07 '23 at 14:23
  • 1
    That is why it is important to output the whole path, not just `$folder.Name` – Theo Feb 07 '23 at 14:24
  • @Theo ok got your point will work on it now, thanks – John John Feb 07 '23 at 14:26
  • @Theo ok i will show the `serverrelativeurl` .. so the object will have values such as `ewRoot --> dv --> test123 --> /dv/test123 NewRoot --> dv --> P100 --> /dv/P100 NewRoot --> dv --> WIP --> /dv/P100/WIP NewRoot --> Site Pages --> Templates --> /SitePages/Templates` – John John Feb 07 '23 at 15:02
  • To get only the top-level folder names you can filter these from the new property `FolderPath` like so: `($csvOutput | Group-Object { ($_.FolderPath -split '/')[1] } ).Name`. Is that what you're after? – Theo Feb 07 '23 at 19:06
  • @Theo `FolderPath` will always be null inside `$csvOutput += [PsCustomObject]@{SiteTitle = $Site.Title; LibraryTitle = $Library.Title; Folder = $folder.Name; FolderPath = $folder.FolderPath}` – John John Feb 07 '23 at 20:08
  • No it should be `FolderPath = $folder.ServerRelativeUrl`, not `FolderPath = $folder.FolderPath`. FolderPath is a property you **create** in the output using the `$folder.ServerRelativeUrl` property – Theo Feb 07 '23 at 21:36

1 Answers1

0

OK, based on our comments, I think what you want to do is this.
It iterates through the entire folder list, but uses a hashtable to make sure you only collect a unique list of top-level folders.

$AdminUrl = "https://***-admin.sharepoint.com/"
Connect-PnPOnline -Url $AdminUrl -Interactive 
 
#sharepoint online get all site collections PowerShell
$SiteColl   = Get-PnPTenantSite
# create a list to store the results
$csvOutput  = [System.Collections.Generic.List[object]]::new()
# create a Hashtable to eliminate any duplicates
$hashUnique = @{}
 
#sharepoint online PowerShell iterate through all site collections
foreach($Site in $SiteColl) {
    Connect-PnPOnline -Url $Site.Url -Interactive
    $Webs = Get-PnPSubWeb -Recurse -IncludeRootWeb
               
    #Get All document libraries
    foreach($Web in $Webs) {
        $DocumentLibraries = Get-PnPList -Web $Web | 
                             Where-Object {$_.BaseType -eq "DocumentLibrary" -and 
                                           $_.Title -ne "Site Assets" -and 
                                           $_.Hidden -eq $false}
        #Iterate through each document library
        foreach($Library in $DocumentLibraries) {
            Get-PnPFolder -List $Library | ForEach-Object {
                # from the ServerRelativeUrl property, split out the 1st level folder name
                $topFolder = ($_.ServerRelativeUrl -split '/')[1]
                if (!$hashUnique.ContainsKey($topFolder)) {
                    # remember we have already seen this 1st level folder so we don't add it again
                    $hashUnique[$topFolder] = $true
                    Write-Host "$($Site.Title) --> $($Library.Title) --> $topFolder"
                    # add an object to the output list
                    $csvOutput.Add([PsCustomObject]@{
                        SiteTitle    = $Site.Title
                        LibraryTitle = $Library.Title
                        Folder       = $topFolder
                    })
                }
            }
        }
    }
}
# now write the csv
$csvOutput | Export-Csv -NoTypeInformation -Path "D:\FirstLevel Folders.csv"
Theo
  • 57,719
  • 8
  • 24
  • 41