Search code examples
powershellactive-directoryldap

powershell script for ldif file


How to write a powershell script to extract records not having goEmpid and output into a file For ldif file containing this

"dn: cn=username,ou=organisationname,ou=org-ca,ou=go-pki,o=finance of organisation,st=on,c=ca,
cn:username mail:[email protected]
uid: username
goEmpid:2273773

dn: cn=username1,ou=organisationname,ou=org-ca,ou=go-pki,o=finance of organisation,st=on,c=ca,
cn:username1 mail:[email protected]
uid: username1

dn: cn=username2,ou=organisationname,ou=org-ca,ou=go-pki,o=finance of organisation,st=on,c=ca,
cn:username2 mail:[email protected]
uid: username2

dn: cn=username3,ou=organisationname,ou=org-ca,ou=go-pki,o=finance of organisation,st=on,c=ca,
cn:username3 mail:[email protected]
uid: username3
goEmpid:2273776"
# the path to LDIF file
$ldifFilePath = "C:\Users\91701\Desktop\pki.ldif"

# the path for the output file
$outputFilePath = "C:\Users\91701\Desktop\output.txt"

# Reading the content of the LDIF file
$ldifContent = Get-Content $ldifFilePath -Raw

# Split LDIF content into individual records
$ldifRecords = $ldifContent -split "^\s*$" | Where-Object { $_ -match '\S' }

# Initializing an empty array to store records with missing 'goEmpid'
$missingGoEmpidRecords = @()

# Loop through each record and check if 'goEmpid' is missing
foreach ($record in $ldifRecords) {
    if ($record -notmatch 'goEmpid') {
        $missingGoEmpidRecords += @"
        Record with missing 'goEmpid':
     $record
    -------------------------
     "@
}

}

# Output the missing 'goEmpid' records to the console
Write-Output $missingGoEmpidRecords

# Save the output to a file
$missingGoEmpidRecords | Out-File -FilePath $outputFilePath -Append

Q This gives me an empty file without displaying records missing goEmpid`'


Solution

  • Ok so first I'm assuming LDIF is LDAP Data Interchange Format, but it looks like your data is a little bit mangled, as your dn ends with a comma and your cn: and mail: are both on the same line.

    I'm going to change it to this for the sake of this answer:

    $data = @"
    dn: cn=username,ou=organisationname,ou=org-ca,ou=go-pki,o=finance of organisation,st=on,c=ca
    cn:username
    mail:[email protected]
    uid: username
    goEmpid:2273773
    
    dn: cn=username1,ou=organisationname,ou=org-ca,ou=go-pki,o=finance of organisation,st=on,c=ca
    cn:username1
    mail:[email protected]
    uid: username1
    
    dn: cn=username2,ou=organisationname,ou=org-ca,ou=go-pki,o=finance of organisation,st=on,c=ca
    cn:username2
    mail:[email protected]
    uid: username2
    
    dn: cn=username3,ou=organisationname,ou=org-ca,ou=go-pki,o=finance of organisation,st=on,c=ca
    cn:username3
    mail:[email protected]
    uid: username3
    goEmpid:2273776
    "@
    

    The next thing is probably to parse the data into records that we can work with easier. This is by no means a complete LDIF parser, but it works for your sample data so hopefully i's good enough to work with the rest of it as well...

    function ConvertFrom-Ldif
    {
        param(
           [Parameter(Mandatory=$True)]
           [string] $ldif
        )
        $records = @( $ldif -split "`n`n" );
        $records | foreach-object {
            $fields = $_ -split "`n"
            $record = $fields | foreach-object `
                -begin {
                    $properties = [ordered] @{}
                } `
                -process {
                    $split = ($_ -split ":").Trim()
                    $properties[$split[0]] = $split[1]
                } `
                -end {
                    return [pscustomobject] $properties
                }
            $record
        }
    }
    

    This gives:

    $records = ConvertFrom-Ldif $data
    $records | format-list *
    
    dn      : cn=username,ou=organisationname,ou=org-ca,ou=go-pki,o=finance of organisation,st=on,c=ca,cn
    mail    : [email protected]
    uid     : username
    goEmpid : 2273773
    
    dn   : cn=username1,ou=organisationname,ou=org-ca,ou=go-pki,o=finance of organisation,st=on,c=ca,cn
    mail : [email protected]
    uid  : username1
    
    dn   : cn=username2,ou=organisationname,ou=org-ca,ou=go-pki,o=finance of organisation,st=on,c=ca,cn
    mail : [email protected]
    uid  : username2
    
    dn      : cn=username3,ou=organisationname,ou=org-ca,ou=go-pki,o=finance of organisation,st=on,c=ca,cn
    mail    : [email protected]
    uid     : username3
    goEmpid : 2273776
    
    

    And now we can filter to get just the records that have a goEmpId property:

    $filtered = $records | where-object { @($_.psobject.Properties.Name) -contains "goEmpid" }
    $filtered | format-list *
    
    dn      : cn=username,ou=organisationname,ou=org-ca,ou=go-pki,o=finance of organisation,st=on,c=ca,cn
    mail    : [email protected]
    uid     : username
    goEmpid : 2273773
    
    dn      : cn=username3,ou=organisationname,ou=org-ca,ou=go-pki,o=finance of organisation,st=on,c=ca,cn
    mail    : [email protected]
    uid     : username3
    goEmpid : 2273776
    

    And then finally we can convert the filtered records back to an ldif text string:

    function ConvertTo-Ldif
    {
        param(
           [Parameter(Mandatory=$True)]
           [object[]] $objects
        )
        $records = @( $objects | foreach-object {
            $fields = $_.psobject.Properties | foreach-object {
                "$($_.Name): $($_.Value)"
            }
            return @($fields) -join "`n"
        })
        @($records) -join "`n`n"
    }
    

    to give:

    $ldif     = ConvertTo-Ldif $filtered
    $ldif
    
    dn: cn=username,ou=organisationname,ou=org-ca,ou=go-pki,o=finance of organisation,st=on,c=ca
    cn: username
    mail: [email protected]
    uid: username
    goEmpid: 2273773
    
    dn: cn=username3,ou=organisationname,ou=org-ca,ou=go-pki,o=finance of organisation,st=on,c=ca
    cn: username3
    mail: [email protected]
    uid: username3
    goEmpid: 2273776