How can I create each folder once while processing CSV shortcuts in PowerShell?

0
0
Asked By QuietMaple42 On

I need to regularly migrate shortcuts using PowerShell. An API export produces CSV rows containing a user ID, folder name, parent ID, target ID, and shortcut name. Rows with a folder name of should create the shortcut directly in the root. For other folder names, the script must first create the folder through an API POST, capture the newly returned folder ID, and then create the shortcut under that folder.

The CSV can contain multiple shortcuts in the same folder, such as several rows for Archive or Personal. Therefore, each non-root folder should be created only once, while every shortcut row still needs to be processed. The destination starts empty, so checking for existing folders or shortcuts is not required.

I initially used nested loops and considered extracting unique folder names first, but I am unsure how to associate the created folder IDs with the correct users and shortcut rows. What is the cleanest PowerShell workflow for creating folders once and reusing their IDs for subsequent shortcuts?

3 Answers

Answered By BrightHarbor6 On

Another straightforward approach is a two-pass process. First group the non-root rows by the scope that defines folder uniqueness, create one folder for each group, and store the returned IDs. Then process the original CSV and create every shortcut using the appropriate stored ID.

In outline:

$rows = Import-Csv $infile
$folderIds = @{}

$groups = $rows | Where-Object FOLDERNAME -ne '' | Group-Object USERID,PARENTID,FOLDERNAME

foreach ($group in $groups) {
$sample = $group.Group[0]
$result = New-Folder -ParentId $sample.PARENTID -Name $sample.FOLDERNAME
$key = '{0}|{1}|{2}' -f $sample.USERID,$sample.PARENTID,$sample.FOLDERNAME
$folderIds[$key] = $result.id
}

foreach ($row in $rows) {
if ($row.FOLDERNAME -eq '') {
$parentId = $row.PARENTID
} else {
$key = '{0}|{1}|{2}' -f $row.USERID,$row.PARENTID,$row.FOLDERNAME
$parentId = $folderIds[$key]
}

New-Shortcut -ParentId $parentId -TargetId $row.TARGETID -Name $row.SHORTCUTNAME
}

This makes the separation between folder creation and shortcut creation very clear. It also avoids repeatedly calling the folder endpoint for rows that belong to the same folder.

Answered By SilverOtter7 On

You do not need a nested loop. Import the CSV once, then either create all unique folders first or keep a cache of folders already created. A hashtable is a good fit because it maps a folder key to the folder ID returned by the API.

For example:

$rows = Import-Csv -Path $infile
$folderIds = @{}

foreach ($row in $rows) {
if ($row.FOLDERNAME -eq '') {
New-Shortcut -ParentId $row.PARENTID -TargetId $row.TARGETID -Name $row.SHORTCUTNAME
continue
}

# Include the user and parent in the key if folder names are only unique within those scopes.
$key = '{0}|{1}|{2}' -f $row.USERID,$row.PARENTID,$row.FOLDERNAME

if (-not $folderIds.ContainsKey($key)) {
$response = New-Folder -ParentId $row.PARENTID -Name $row.FOLDERNAME
$folderIds[$key] = $response.id
}

New-Shortcut -ParentId $folderIds[$key] -TargetId $row.TARGETID -Name $row.SHORTCUTNAME
}

The API commands above are placeholders for the actual POST logic. The important part is that the folder POST runs only when the key is not already in the hashtable, and every row then uses the cached ID.

CobaltPine19 -

Using only the folder name as the key is safe only if names are globally unique. If two users can each have an Archive folder, use a composite key such as user ID plus parent ID plus folder name.

Answered By MellowCedar88 On

The state variables in the proposed if/elseif version will not work reliably if they are reset inside the row loop. Comparing the current folder name with only the immediately previous response also assumes the CSV is sorted and does not handle multiple users or parent folders correctly.

Use a hashtable or dictionary instead. It remembers every folder created so far, regardless of where its rows appear in the CSV. Also, the sample data does not contain a TYPE column, so either add that column to the CSV or remove the unused TYPE reference from the script.

Related Questions

LEAVE A REPLY

Please enter your comment!
Please enter your name here

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