ReplaceAll

Create a folder structure in SharePoint Online using PowerShell PnP (from file shares)

Recently, I had to create a SharePoint folder structure extracted from a file share. I only wanted the structure, and not the files.

So I had the local part to extract what I needed, and then I thought “sure I’ll use PowerShell PnP with a foreach loop, and done!”
Well, surprisingly (or not), that didn’t work as expected 😟 So after a few hours trying and trying again, I decided to ask for help… (Never be afraid to ask for help, because you’ll 100% learn something!)

In this blog post, I’m going to share the script that Adam Listek (@alistek) made within a few minutes, and help me tremendously (I have his permission for sharing). Thanks Adam! 😊

ℹ️ Here, I’m not going to debate if folders are good or bad. Each requirement is different for each project so… It always depends!

 

Extract structure from File Shares

The below one-liner allowed me to export the root folder as well as all nested folders like I needed.

Get-ChildItem -Path '\\<SharedDrive>\RootFolder' -Recurse -Directory | select FullName | Export-Csv -Path "C:\users\$env:USERNAME\Desktop\myFolderStructure.csv" -NoTypeInformation

Results would look like this: (this is an extract of my cloned repos on Github)

Github_Extract
my Github repos extract

 

So… I’m using… :

  • -Recurse parameter to get the nested folders
  • -Directory parameter to get only the folders (not the files)
  • FullName property will give me the full path
  • -NoTypeInformation to avoid too much info at the top of the excel file…

Now that we have the original structure, let’s modify it a little bit.

  • Ctrl+F on the keyboard,
  • Replace tab,
  • Enter the location for the root folder (C:\Github\ in my case),
  • Replace All
  • And poof!

We have what we want! 😎

ReplaceAll

Results

 

 

Create the structure in SharePoint Online

Now’s the time to make it like a breeze… I’ll spare you my hair pulling theories, which were too complex when simplicity should have been thought through…

I will however, explain the logic and requirements behind it.
On this extract above, we have folders alone (i.e.: Dev-SPFarm-2016), and we have nested folders (i.e.: vPS365\docs)

Folders alone are not such a big deal to create. But nested folders… they need the ‘root’ to be created before right? 😉

So here we go. This is what we need to do: (change to YOUR TENANT NAME, SITE, and DOC LIBRARY)

  • Connect to the site collection (where the library is)
  • Declare the structure
    • If not too long, it’s easy to insert in the script.
    • If too long, just replace by Import-Csv -Path <Your_Csv_file>
  • Declare the document library (which you’ll find in the URL – not the display name with any space you may have created it!)
  • And then we start creating the structure.
    • Set the $i = 0
    • Loop through each item,
    • Condition if ‘root’ or subfolder
    • Set the -ErrorAction to ‘SilentlyContinue’ if you don’t want to see red when the ‘root’ folder is already created
    • A bit of artefacts with -ForegroundColor
    • Use the Add-PnPFolder cmdlet for creation
    • Insert $i++ to continue as long as we have folders to create!
#Connect- to SPO site
Connect-PnPOnline -Url 'https://<YOUR_TENANT_NAME>.sharepoint.com/sites/<YOUR_SITE>'

#array of folders
$paths = @(
    "Dev-SPFarm-2016"
    "O365-Data-Retriever-Tool"
    "O365_EXO_PowerShellScripts"
    "O365_LCSING_PowerShellScripts"
    "O365_SPO_PowerShellScripts"
    "O365_SPO_Reports"
    "SharePointServer_PowerShellScripts"
    "vPS365"
    "Dev-SPFarm-2016\screenshots"
    "O365-Data-Retriever-Tool\.github"
    "O365-Data-Retriever-Tool\assembly"
    "O365-Data-Retriever-Tool\Images"
    "O365-Data-Retriever-Tool\resources"
    "O365-Data-Retriever-Tool\screenshots"
    "O365-Data-Retriever-Tool\.github\ISSUE_TEMPLATE"
    "O365_SPO_Reports\Get-SPOSiteInfo"
    "O365_SPO_Reports\Get-SPOSiteInfo\screenshots"
    "vPS365\docs"
    "vPS365\functions"
)

#Declare the Document Library
$topLevelRoot = '/TargetLibrary'

#Create the structure
$paths | Foreach-Object {
    $split = $_ -Split "\\"
    $root = $null
    $previousRoot = $null    

    $i = 0

    $split | Foreach-Object {
        If ($i -NE 0) {
            $previousRoot = $root
            $root = (Join-Path $root $_)
            $current = $_
            
            Write-Host "Sub-Folder Name: $current | Library: $previousRoot" -ForegroundColor Green 
            Add-PnPFolder -Name $current -Folder $previousRoot -ErrorAction SilentlyContinue
        }
        Else {
            $root = Join-Path $topLevelRoot $_
            $current = $_
            
            Write-Host "Folder Name: $current | Library: $topLevelRoot" -ForegroundColor Cyan 
            Add-PnPFolder -Name $current -Folder $topLevelRoot -ErrorAction SilentlyContinue
        }

        $i++
    }
}

Now let’s run this, and observe the magic 🥳

 

Thank you Adam! 👍

 

Leave a Reply