henrycarteruk
henrycarteruk

Reputation: 13227

powershell - compare username to a csv and report non-matches

I'm migrating users from a legacy system into Active Directory and need to add them into an AD group. Usernames don't match (or have any logic!) between the two systems so I've got a csv with the old and new usernames in:

Input.csv:

SamAccountName,LegacyUsername
ChristopherSpraggons,CSprag
JakeSquirrell,JakeSq
GeorgeCornish,CornishG

I've written the powershell to do the lookup and add the user to the group but ideally need it to report any users that it cannot match out to a txt file so they can be done manually. I'm totally stuck on how to do this.

Here's what I have so far:

$ImportCSV = C:\TEST.csv
Import-module ActiveDirectory 
$InputCSV=get-content $ImportCSV
$MatchedUsers = Import-CSV 'Input.csv' | Where{$InputCSV -match $_.LegacyUsername} | ForEach-Object {Add-ADGroupMember -Identity "ADGroupName" -Member $_.SamAccountName}

TEST.csv is just plain a list of legacy usernames with no headings.

Upvotes: 2

Views: 5127

Answers (2)

Austin T French
Austin T French

Reputation: 5140

Assuming you have headers in your CSV, you should be able to use PowerShell's array methods easily without manually enumerating both CSVs repeatedly.

$ImportCSV = C:\TEST.csv
Import-Module ActiveDirectory
$InputCSV = Get-Content $ImportCSV | `
 ForEach-Object {
if ($ImportCSV -notcontains $_.UserName) {
 $_ | Out-File C:\MissingNames.txt -Append
} }

Upvotes: 0

Ansgar Wiechers
Ansgar Wiechers

Reputation: 200483

Don't filter the CSV data before the loop. Instead, put an conditional inside the loop and add the non-matching names to a second array:

Import-Module ActiveDirectory

$legacyNames = Get-Content 'C:\TEST.csv'

$NonMatchedUsers = @()
$MatchedUsers = Import-CSV 'Input.csv' | % {
    if ( $legacyNames -contains $_.LegacyUsername ) {
      Add-ADGroupMember -Identity "ADGroupName" -Member $_.sAMAccountName
      $_.sAMAccountName
    } else {
      $NonMatchedUsers += $_.sAMAccountName
    }
  }

I'd rename TEST.csv to something like LegacyNames.txt, though, because it isn't a CSV in the first place.

Edit: Since you want TEST.csv to be the actual input I'd suggest a slightly different approach. Load Input.csv into a hashtable (a dictionary) and make TEST.csv the input for the pipeline:

Import-Module ActiveDirectory

$mapping = @{}
Import-Csv 'Input.csv' | % { $mapping[$_.LegacyUsername] = $_.sAMAccountName }

$NonMatchedUsers = Get-Content 'TEST.csv' | % {
    if ( $mapping.contains($_) ) {
      Add-ADGroupMember -Identity "ADGroupName" -Member $mapping[$_]
    } else {
      $_
    }
  }

Upvotes: 2

Related Questions