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
|
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
This is what we need:
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!