I'm trying to write a Powershell script that will import a list of computer names from a CSV file and compare it against all computer names in AD. I need it to output a list of names from the CSV file that do not exist in AD.
I have been playing around with these commands but they don't do exactly what I want.
$import = Import-Csv -Path C:\Users\username\Desktop\test.csv
$AD-Names = Get-ADComputer -filter * | Select -Expand Name
Compare-Object $import $AD-Names
This seems to give me a list of everything different from both variables which is an extremely long list. I really just need to know which computer names in the CSV file are not in AD.
Simply compare the names from your CSV against the list of names from AD (I'm going to assume that the column title of the CSV is Name):
$ADNames = Get-ADComputer -Filter * | Select-Object -Expand Name
Import-Csv 'C:\path\to\input.csv' |
Where-Object { $ADNames -notcontains $_.Name } |
Export-Csv 'C:\path\to\not_in_AD.csv' -NoType
Side note: $AD-Names is not a valid variable name. Change the hyphen to an underscore or remove it entirely, or put the variable name in curly brackets (${AD-Names}).
First, why do you need a csv file if there are only computer names ?
CSV files are usually used to store a table in a simple text file.
If your CSV only contains the computer names, and you only want to check for computer names, this could work for you :
$OutputComputers = #();
$InputComputers = Import-Csv input.csv -Header ComputerName;
$AdComputers = Get-ADComputer -Filter 'Name -like "*"';
$InputComputers | ForEach-Object {$i = 0} {
if ($_.ComputerName -notin $AdComputers.Name) {
$OutputComputers += New-Object PsObject -property #{
'ComputerName' = $_.ComputerName
}
}
}
$OutputComputers | Export-Csv output.csv -Delimiter ";" -Encoding UTF8 -Force -NoTypeInformation
Hope it helps.
Related
I'm trying to compare 2 files that both contain email addresses. For example text1.csv has 800 addresses and text2.csv has 200. Most of the email addresses in text2.csv are in text1.csv but not all of them. I need to export all the email addresses from text2.csv that are NOT in text1.csv. The property on both files is email
I tried something like this but I dont get the correct outcome:
Compare-Object -ReferenceObject (Get-Content -Path C:\scripts\test1.csv) -DifferenceObject (Get-Content -Path C:\scripts\test2.csv) | Where-Object{ $_.SideIndicator -eq "=>" }
I also tried this without result
$file2 | Where-Object { $_.email -NotIn $file1 }
By using Get-Content, you end up comparing whole lines from your input files.
In order to compare column values from CSV files, you must first convert your input files to objects, using Import-Csv, whose properties (reflecting the column values) you can then compare; in your case, the .email property:
Compare-Object -PassThru (Import-Csv C:\scripts\test1.csv).email `
(Import-Csv C:\scripts\test2.csv).email |
Where-Object{ $_.SideIndicator -eq '=>' }
Note:
Compare-Object's -PassThru switch directly passes the differing objects through, decorated with a .SideIndicator ETS property, instead of wrapping them in a [pscustomobject] wrapper whose .InputObject contains the respective original object.
Even though, with multiple data rows in the CSV, Import-Csv returns an array of objects, you can access .email directly on that array in order to get the property values of all elements in the array, which is a convenient feature known as member-access enumeration.
For brevity, I'm using positional arguments above (e.g., C:\scripts\test1.csv instead of -Path C:\scripts\test1.csv).
I'd probably do something like this:
$emails = (Import-Csv -Path 'X:\file1.csv').email
$result = Import-Csv -Path 'X:\file2.csv' |
Where-Object { $emails -notcontains $_.email }
# output to new file
$result | Export-Csv -Path 'X:\missingEmails.csv' -NoTypeInformation
I've written a script to extract a list of all AD groups name, that then feeds it into the next section which exports a number of CSV files based on the name of the group:
import-module active directory
New-Item -Path "c:\" -Name "ADlist" -ItemType "directory"
get-adgroup -filter * | sort name | select Name | export-csv -Path c:\ADlist\adlist.csv
$ADlist = Import-Csv -Path "c:\ADlist\adlist.csv"
foreach ($ADgroup in $ADlist)
{
$export = get-ADGroupMember -identity $ADgroup.name | select name |Export-Csv "$ADgroup.csv" -notypeinformation
}
this works, however, the csv names are outputting weirdly and looks similar to:
#{Name=$ADgroup}
instead of simply
$ADgroup
is there a way to correct this to output as such?
Your last Export-Csv "$ADgroup.csv" is stringifying your $ADGroup object. Since that object has a property called Name and an associated value, you are seeing the result in that format. You should change that to the following:
$export = Get-ADGroupMember -Identity $ADgroup.name |
Select-Object Name |
Export-Csv "$($ADgroup.Name).csv" -NoTypeInformation
You can see this behavior by just surrounding a custom object in quotes or using Write-Host.
"$ADgroup"
Write-Host $ADgroup
I require to exclude user profiles from \\Computer\c$\Users folder when using Get-ChildItem.
I potentially need to exclude 100 profiles from various machines so have created a variable that contains all user profiles from an AD security group that I want excluding but when I run the below command it doesn't work but if I list the profiles in plain text it does work.
Get-ChildItem "\\$computer\c$\Users" -Exclude $ListOfUsers
But works if I run Get-ChildItem "\\$computer\c$\Users" -Exclude Bob1,Bob2,Bob3,Bob4,Bob5
My code to obtain the users from AD security groups are below and the format it outputs to is like the above with commas.
## collects users from groups and adds to exlusion list.
$1stline = Get-ADGroupMember GG_1st_Line_Team | Select SamAccountName
$2ndline = Get-ADGroupMember GG_2nd_Line_Team | Select SamAccountName
$3rdline = Get-ADGroupMember GG_3rd_Line_Team | Select SamAccountName
$FieldTech = Get-ADGroupMember "Field tech" | select SamAccountname
$Excluded = $1stline + $2ndline + $3rdline + $Fieldtech | Out-File "C:\temp\Members.txt"
(get-content c:\temp\Members.txt) -join "," | out-file C:\temp\Format.txt
$format = get-content c:\temp\format.txt; $format = $format -replace '\s',''; $format = $format -replace ',SamAccountName,--------------,',''; $format = $format.trimend(",,") | Out-File "C:\temp\newFormat.txt"
$excluded = Get-Content C:\Temp\newFormat.txt
This will create a text file with 100 names with no spaces, only commas to seperate the users. If I Write-Host the variable $newformat the commas are White along with the text but if I put the Profile names in plain text then the commas are grey...
The excessive use of Out-File is unnecessary and will cause you issues as it changes objects into strings. You then have to use commands like Split and Join to turn the strings back into the object (arrays here) you require.
Out-File should only be used when you actually need the output as a file.
With a few simple changes to your script it'll do what you want, and be a lot simpler too!
You can use ExpandProperty to only return the value of SamAccountName itself as a string rather than an object.
You can then simply create an array of those strings and use this to exclude those accounts/folders from Get-ChildItem,
$1stline = Get-ADGroupMember GG_1st_Line_Team | Select-Object -ExpandProperty SamAccountName
$2ndline = Get-ADGroupMember GG_2nd_Line_Team | Select-Object -ExpandProperty SamAccountName
$3rdline = Get-ADGroupMember GG_3rd_Line_Team | Select-Object -ExpandProperty SamAccountName
$FieldTech = Get-ADGroupMember "Field tech" | Select-Object -ExpandProperty SamAccountname
$excluded = $1stline,$2ndline,$3rdline,$Fieldtech
Get-ChildItem "\\$computer\c$\Users" -Exclude $excluded
You could then look into using a foreach loop with Get-ADGroupMember to cut down on the duplicated Get-ADGroupMember code.
The problem here seems to be that you're using a [string] variable with a value of Tom,Dick,Harry.
I bet you've got no folders like this, have you?
Whilst you can pass a [string] in to the -Exclude parameter; that will be a singleton (a single, scalar value); and the best you'll get is a single exclusion.
What you really want to pass in is a string array: [string[]]!
[string]$excludedString = "Tom,Dick,Harry"
[string[]]$excludedArray = $excludedString -split ","
Get-ChildItem -Path "C:\users" -Exclude $excludedArray
I am currently working with a CSV file that has a manager's employee number, but not their SAMAccountName. I want to utilize Get-ADUser to grab the manager's SAMAccountName from their EmployeeNumber attribute and place that inside a new column in the same CSV file.
CSV sample:
"Full Name","Username","Manager","Manager User Sys ID"
"User 1","u1","1, Manager","123456"
"User 2","u2","2, Manager","234567"
"User 3","u3","3, Manager","345678"
I would like:
"Full Name","Username","Manager","Manager User Sys ID","Manager SamAccountName"
"User 1","u1","1, Manager","123456","m1"
"User 2","u2","2, Manager","234567","m2"
"User 3","u3","3, Manager","345678","m3"
I have spent some time putting together the following code. I can get a new column added and can further grab the SAMAccountName, but it only exports a single line in the new CSV file like this:
"SAMAccountName","managerUsername"
"m1","#{SAMAccountName=m1}"
Here is the code:
$managers = Import-Csv -Path .\test.csv
$usermananger = #()
foreach ($manager in $managers)
{
$getmanagersam = Get-ADUser -Filter "employeeNumber -eq $($manager."Manager User Sys ID")" -Properties SAMAccountName |
Select-Object SAMAccountName
$exportstring = $testmanager |
Select-Object *,#{Name='managerUsername';Expression={"$getmanagersam"}}
$exportstring | Export-Csv -Path .\simpletest.csv -NoTypeInformation
}
As #MathiasR.Jessen mentioned in the comments: you need to expand the SamAccountName property to get just the value. Also, you're overwriting your output CSV with every iteration. Either append to the file, or move the Export-Csv cmdlet outside the loop. The former requires PowerShell v3 or newer, the latter requires that you change the loop to a ForEach-Object loop (or run the foreach loop in a subexpression).
Personally I'd prefer using a pipeline, so I'd pick the latter:
Import-Csv -Path .\test.csv | ForEach-Object {
$acct = Get-ADUser -Filter "employeeNumber -eq $($_.'Manager User Sys ID')" |
select -Expand SamAccountName
$_ | select *,#{Name='managerUsername';Expression={$acct}}
} | Export-Csv -Path .\simpletest.csv -NoTypeInformation
The short answer is to add the -Append option to your export-csv statement to stop it overwriting each time round the loop.
Alternatively move the export outside the loop as follows:
$managers = Import-Csv -Path .\test.csv
$managers|foreach-object{
$getmanagersam = Get-ADUser -Filter "employeeNumber -eq $($_.'Manager User Sys ID')" | select -ExpandProperty SAMAccountName
$_|Select *,#{Name='managerUsername';Expression=$getmanagersam}
} | Export-Csv -Path .\simpletest.csv -NoTypeInformation
Note: looks like #AnsgarWiechers beat me to it :-)
I'm late to the party it looks like, but that rarely stops me... I'm not a huge fan of adding properties via the Select cmdlet, so I'm going to offer an alternative where you pipe the CSV to a ForEach-Object loop (just like the other answers), but inside that you use Add-Member with the -PassThru argument, and then pipe it off to the output file. I will add a new line and indent after the pipes, just to make it easier to read.
Import-Csv -Path ".\test.csv" |
ForEach-Object {Add-Member -InputObject $_ -NotePropertyName 'managerUserName' -NotePropertyValue (Get-ADUser -Filter "employeeNumber -eq $($_.'Manager User Sys ID')").samaccountname -PassThru} |
Export-Csv -Path ".\simpletest.csv" -NoTypeInformation
This should essentially do the exact same thing as the other two answers, it just adds the property differently, because variety is the spice of life! (I saw that on the internet somewhere, so it must be true.)
I am still on the learning curve with powershell, i currently have the following script:
$users = Get-Acl $Path |
Select-Object -ExpandProperty access |
ft identityreference |
where { $_.identityreference -like "UK\"}
$Path is the location of a particular share on a server. I currently have a CSV file called "test" with about 100 share names on the same server (The first column heading named "ShareNames"), the second column is named "GroupName".
I need to update this script to search through the first column in the CSV file called "test.csv" and push out the appropriate group permission to that share in the second column. I have to also admit the last part of the script does not work :( i am having trouble filtering out a common group name we have as i do not want the whole list of groups for every share only group names that start with ("uk\gro...").
Thank you for any guidance / help
I would choose -match over -like and skip the Format-Table. The following would filter the ACEs on their property IdentityReference using the regex ^UK\\ -- I am assuming that 'UK\' is the domain portion of the group name within the ACEs:
$user = Get-Acl $path |
Select-Object -ExpandProperty access |
Where-Object { $_.IdentityReference -match '^UK\\' }
Then you can ft as desired:
$user | Format-Table
If you need to feed in a CSV of paths, you can pipe an Import-Csv into a ForEach-Object wrapped around the above example.
Import-Csv test.csv |
ForEach-Object {
Write-Output "ACEs on $($_.ShareNames) matching 'UK\'"
Get-Acl $_.ShareNames |
Select-Object -ExpandProperty access |
Where-Object { $_.IdentityReference -match '^UK\\' }
}
I'm still not clear on how you intend to populate the "GroupName" column in the output as there could be multiple entries for groups beginning with 'UK\'.