PowerCLI to Generate Nested VM Folder Structure

PowerCLI to Generate Nested VM Folder Structure

We are currently starting to plan for a disaster  recovery test, and the first part is configuring Site Recovery Manager (SRM).  We are still in the middle of the infrastructure replacement, so we are starting from scratch with everything.  So for SRM to work the best we need to have identical folder structures in both locations.

The folder structure in our main vSphere data center has 555 folders, which most of them are nested folders.  I need to figure out a way to create an identical copy of this structure in our recovery site.  This was isn’t an easy feat, but give me a PowerShell and PowerCLI, and I’ll figure it out.

Nested Folders
With over five hundred folders this definitely wasn’t the case.

Gather the Folder Structure to be Generated

Before taking the time to write any script, I normally google the issue to see if anyone else has ran into the issue.  No sense writing a script that has already been done.  So I found a way to pull the folder structure using a script wrote by Luc Dekens.

http://www.lucd.info/2010/10/21/get-the-folderpath/

Using this function that Luc wrote, I was able to export the folder structure from vSphere using the following script.

Get-folder -type VM | Foreach {($_ | Get-FolderPath).Path | Out-file C:\scripts\logs\Folders.txt -Append}

Example of the output from the script above:

Example of Nested Folder Export
Example of the Nested Folder Export from Get-FolderPath Function

Making the Folders

So now that I have the folder structure in a text file, I can start the new folder creation, right?  How?

There is a PowerCLI command, New-Folder.  This is a great start, but how do I feed it my output from the last script to make the folders structure.  I can read the file into a script, but I’ll then need to split the folders at the ‘\’, which isn’t difficult.  Its making the nested folders that is the tricky part as I have multiple folders with the same name.  For example, I have 24 folders with the name UAT, so if i just run Get-folder -name ‘UAT’, the results are not ideal as seen below.

That is a lot of UAT folders
Results of Get-Folder -Name ‘UAT’

In order to be able to target the correct folder when creating the nested folders, I’ll need to be able to determine the parent folder.  Then if the parent folder to that is not a root folder, I’ll need to know the parent to that folder and so on.  My head is spinning just thinking of this.

Are you my parent?

To get the parent of a folder you will just need to enumerate additional information when running the Get-Folder command.

You're nested in Linux
Detailed information about a folder

So there are 2 different ways to target the parent folder, using the ID or the name.  I prefer to use the ID as it is a unique identifier so I don’t have issues once I get deep into the nested folders by targeting the incorrect folder.

The Script that Makes Nests

Below is the script that creates the nested folders.

$ErrorActionPreference = 'SilentlyContinue'
$folders = get-content C:\scripts\logs\folders.txt
Foreach ($Folder in $folders){
    $Path = $folder
    $SplitPath = $Path.split('\')
    
    $SplitPath = $SplitPath | Where {$_ -ne "DataCenterName"}
    Clear-Variable Folderpath
    Clear-Variable Parent

    Foreach ($directory in $SplitPath){
        If ($Folderpath -ne $Null){
            IF ($(Get-folder $directory | Where Parentid -eq $($Folderpath.id)) -eq $Null){
                Write-Host "Generating new folder $directory" -ForegroundColor Green -BackgroundColor Black
                Get-Folder -id $parent | New-Folder $directory
            }
            Else{
                Write-host "Folder $directory Exists!" -ForegroundColor Magenta -BackgroundColor Black
                $Folderpath = Get-Folder $directory | Where Parentid -eq $($Folderpath.id)
                $Parent = $Folderpath.Id
            }
        }
        Else {
            $FolderExist = Get-folder -Name $directory
            IF ($FolderExist -eq $Null){
                Write-host "Generating new folder $directory" -ForegroundColor DarkGreen -BackgroundColor Black
                New-folder -Name $directory -Location VM
                $Folderpath = Get-folder $directory
            }
            Else{
                Write-host "Folder $directory Exists!" -ForegroundColor DarkMagenta -BackgroundColor Black
                $Folderpath = Get-Folder $directory
                $Parent = $Folderpath.Id
            }
        }
    }
}

There is the script in all of its glory.

-Stuart

14 thoughts on “PowerCLI to Generate Nested VM Folder Structure”

  1. Thanks for this. I have an issue, when I run the script, it creates all the parent folders but does not actually create the subfolders. The output reads “Generating new folder NewFolder” nut it does not actually create it. I am running this on a vCenter 6.5 U2 environment.

    1. Hello Frank,
      Sorry to hear you are having issues. Would you provide some of the folder output file and any changes you might have made to the script to run in your environment? I’ll try and help to resolve this issue with you.

      -Stuart

  2. Hello Stuart,
    I think you missed to put the $parent variable in the below Else section, thats why as Frank said only “Generating new folder NewFolder” message coming up not creating folders.

    Else {
    $FolderExist = Get-folder -Name $directory
    IF ($FolderExist -eq $Null){
    Write-host “Generating new folder $directory” -ForegroundColor DarkGreen -BackgroundColor Black
    New-folder -Name $directory -Location VM
    $Folderpath = Get-folder $directory
    }
    Else{
    Write-host “Folder $directory Exists!” -ForegroundColor DarkMagenta -BackgroundColor Black
    $Folderpath = Get-Folder $directory
    }

    1. Rakesh,
      You are very correct. I just used my script, and found this issue as well. Thanks kindly for your update. I have corrected the script in the post.

      -Stuart

  3. For me this script doesn’t do what it needs to do. Not sure if this is because I’ve got 4 nested folders but it makes a mess of the import.

    Initially I thought that this might have something to do with spaces in the input.txt but even without spaces it doesnt work.

    If my input.txt is:
    a\B\c\d1
    a\B\c\d2
    a\B\c\d3
    etc

    I end up with vCenter Folders like: (simple example)
    a\B\d1
    a\B\d2
    a\c

    Needsless to say that the a\c doesnt need to be there.

    1. Kenneth,
      Sorry you are having issues with the script. The environment that I originally used this script had a least 5-6 folders deep. Its very odd that it would make the ‘a\c’ nested folder as the nature of the script is that it looks for the id of the parent folder so it shouldn’t be able to perform this.

      -Stuart

  4. I test skript with 2 cases:
    1. “A\B\C\D\E” – works fine first time -> “A\B\C\D\E”
    2 “B\B\C\D\E” – will create “B\B\C\D\E” + “A\B\B\C\D\E”

    I belive that this need to be added after new folder is created to set new folder as parent
    $Folderpath = Get-Folder $directory | Where Parentid -eq $($Folderpath.id)
    $Parent = $Folderpath.Id

    ———————————————————————–
    Foreach ($directory in $SplitPath){
    $Parent, $Folderpath

    If ($Folderpath -ne $Null){
    IF ($(Get-folder $directory | Where Parentid -eq $($Folderpath.id)) -eq $Null){
    Write-Host “1. Generating new folder $directory” -ForegroundColor Green -BackgroundColor Black
    Get-Folder -id $Parent | New-Folder $directory
    $Folderpath = Get-Folder $directory | Where Parentid -eq $($Folderpath.id)
    $Parent = $Folderpath.Id
    }
    Else{
    Write-host “2. Folder $directory Exists!” -ForegroundColor Magenta -BackgroundColor Black
    $Folderpath = Get-Folder $directory | Where Parentid -eq $($Folderpath.id)
    $Parent = $Folderpath.Id
    }
    }
    Else {
    $FolderExist = Get-folder -Name $directory
    IF ($FolderExist -eq $Null){
    Write-host “3. Generating new folder $directory” -ForegroundColor DarkGreen -BackgroundColor Black
    New-folder -Name $directory -Location VM
    $Folderpath = Get-folder $directory
    }
    Else{
    Write-host “4. Folder $directory Exists!” -ForegroundColor DarkMagenta -BackgroundColor Black
    $Folderpath = Get-Folder $directory
    $Parent = $Folderpath.Id
    }
    }
    }

  5. Well, that just saved me a TON of work! Our AD team redesigned the OU structure and we wanted to match that in vCenter. I exported his AD structure, massaged the data and imported it to Prod and DR sites. Done! Thank you and LucD for this!!

  6. Hey,
    thanks for the script. It has already saved me a lot of time! Now I just wanted to use it again but I got an error:
    + CategoryInfo : ObjectNotFound: (Get-FolderPath:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

    Any idea?

  7. Hi,

    Great script will same us some time.
    The only problem i find is, if the first folder does not exist in the path i want to create it will create all folders in the root.
    For example folder1\folder2\folder3
    will result in
    folder1
    folder2
    folder3

    The same happens in subfolders, for now i just add extra path’s so there will never be more then one extra subfolder created.
    Could this be fixes or is it my error?
    I think it has something to do with the parent folder.

    Kind regards

    1. Jasper,
      I would need to look more into these issues you are facing. I’ll try and duplicate the errors you are talking about to see how to fix them.

      – Stuart

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.