Contents

Create a folder structure in SharePoint using PowerShell (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 (Twitter: @alistek) made within a few minutes, and help me tremendously (I have his permission for sharing). Thanks Adam!

Exctract structure from File Shares

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

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

 

/images/powershell-screenshots/create-folder-structure-img1.png
 

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

/images/powershell-screenshots/create-folder-structure-img2.png
 

This is what we need:

/images/powershell-screenshots/create-folder-structure-img3.png
 

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!
       

Script for MacOS users

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#Connect- to SPO site
Connect-PnPOnline -Url 'https://<TENANT-NAME>.sharepoint.com/sites/<YOUR-SITE>' -Credentials <YOUR-CREDS>

#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"  ### No forward slash in the front ###
Write-Host "Destination library is: " $topLevelRoot -f Cyan

#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 Magenta 
            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++
    }
}

 

Script for Windows users

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#Connect- to SPO site
Connect-PnPOnline -Url 'https://<TENANT-NAME>.sharepoint.com/sites/<YOUR-SITE>' -Credentials <YOUR-CREDS>

#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"  ### No forward slash in the front ###
Write-Host "Destination library is: " $topLevelRoot -f Cyan

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

    $i = 0

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

        $i++
    }
}

 

Thanks for reading!