Concatenate multiple Variables/CSVs and export as one CSV file Powershell - csv

For example,
I have CSV file and imported to powershell
$fullname = Import-Csv “fullname.csv”
$fullname
Output is
FullName
------------------
John Smith
Kevin Johnson
I have another CSV file and imported to
$Email = Import-Csv “Email.csv”
$Email
the output is
Email
-------
jhrjf#gmail.com
hheraf1010#gmail.com
I would like to concatenate this 2 variables and export to as one csv file, so I tried like this
$fullname = Import-Csv “fullname.csv”
$fullname
$Email = Import-Csv “Email.csv”
$Email
($fullname+$Email)|Export-Csv C:\fullnameandEmail.csv -NoTypeInformation
i also try like this
-join($fullname,$Email)|Export-Csv C:\fullnameandEmail.csv -NoTypeInformation
but it was not working,
I would like to make csv like below, how can I concatenate these 2 valuables?
FullName Email
--------- ----------
John Smith jhrjf#gmail.com
Kevin Johnson hheraf1010#gmail.com
Thank you so much

It's helpful to understand that the $fullname and $email objects you have in memory after importing a CSV are actually arrays of objects. Each object has one or more properties that represent the column values from the CSV.
You can loop through the objects in either of the arrays and use the Add-Member cmdlet to add a new property to each object.
The following code loops through the $email array and for each item, it adds a property with the Email value to the corresponding item in the $fullname array. It then exports that merged array to a CSV file.
$fullname = Import-Csv "fullname.csv"
$email = Import-Csv "Email.csv"
$i = 0
$email | ForEach-Object {
Add-Member -inputobject $fullname[$i] -name Email -value $_.Email -membertype NoteProperty;
$i++}
$fullname | Export-Csv -notype -path "C:\fullnameandEmail.csv"

So, for simplicity I would combine what the other two have suggested. Use a For loop, and then within the loop use Add-Member.
$fullname = Import-Csv “fullname.csv”
$Email = Import-Csv “Email.csv”
For($i=0;$i -lt $fullname.count;$i++){
$FullName[$i] | Add-Member 'Email' $Email[$i].email
}
$FullName | Export-CSV -NoType Output.csv

$names = Import-Csv "fullname.csv"
$emails = Import-Csv "email.csv"
for ( $n = 0; $n -lt $names.Count; $n++ ) {
New-Object PSObject -Property #{
"FullName" = $names[$n].FullName
"Email" = $emails[$n].Email
} | Select-Object FullName,Email
}

Related

marge embedded JSON objects with powershell

I have following ConvertFrom-Json output from JSON file:
Id : 1
ItemName : TestFile
SharingInformation : {#{RecipientEmail=complianceadmin#dev.onmicrosoft.com; ResharePermission=Read}, #{RecipientEmail=test#dev.onmicrosoft.com; ResharePermission=Read}}
I would like to save this data to .csv file in following manner as columns:
Id : 1
ItemName : TestFile
Users : (read) test#dev.domain.com ; (write) test2#dev.domain.com
as columns.. Here you can find part of my actual PS code (which do not work properly when there is more than one embedded values):
$JSONFile = $ExctratedFile | ConvertFrom-Json
$psObjectForCsv = $JSONFile | ForEach-Object {
[PSCustomObject]#{
"id"=$_.Id
"ItemName"=$_.ItemName
"RecipientEmail"=$_.SharingInformation.RecipientEmail
"ResharePermission"=$_.SharingInformation.ResharePermission
}
}
$psObjectForCsv | Export-Csv -path $fileName -Force -NoTypeInformation
}
do you have any ideas how to achieve this?
Thank you for your help!
Regards
You can format the SharingInformation in any form you like.
Try
$JSONFile = $ExctratedFile | ConvertFrom-Json
$result = $JSONFile | ForEach-Object {
# output a formatted string "(permission) emailaddress"
$users = foreach ($shareInfo in $_.SharingInformation) {
'({0}) {1}' -f $shareInfo.ResharePermission, $shareInfo.RecipientEmail
}
[PSCustomObject]#{
id = $_.Id
ItemName = $_.ItemName
Users = $users -join "; "
}
}
$result | Export-Csv -Path $fileName -Force -NoTypeInformation

How To Access Specific Rows in an Import-Csv Array?

I need to split a large file upload into many parallel processes and want to use a single CSV file as input.
Is it possible to access blocks of rows from an Import-Csv object, something like this:
$SODAData = Import-Csv $CSVPath -Delimiter "|" |
Where $_.Rownum == 20,000..29,999 |
Foreach-Object { ... }
What is the syntax for such an extraction?
I'm using Powershell 5.
Import-Csv imports the file as an array of objects, so you could do something like this (using the range operator):
$csv = Import-CSv $CSVPath -Delimiter '|'
$SOAData = $csv[20000..29999] | ForEach-Object { ... }
An alternative would be to use Select-Object:
$offset = 20000
$count = 10000
$csv = Import-Csv $CSVPath -Delimiter '|'
$SODAData = $csv |
Select-Object -Skip $offset -First $count |
ForEach-Object { ... }
If you want to avoid reading the entire file into memory you can change the above to a single pipeline:
$offset = 20000
$count = 10000
$SODAData = Import-Csv $CSVPath -Delimiter '|' |
Select-Object -Skip $offset -First $count |
ForEach-Object { ... }
Beware, though, that with this approach you need to read the file multiple times for processing multiple chunks of data.

I want to convert a powershell output into a html file

I wanted to convert a powershell result to html file,
I have an array $f="gsds,jv,hfvw".
I want the html file to print each element of the array in a new line.
How to do it?
Thanks!
I used this code
$f="6e47812,662348,8753478"
Get-Service |ConvertTo-Html -Body "$f"|out-file D:\service.html
And the out put was
6e47812,662348,8753478
Do you mean something like this? :
$test = "abc","def","ghi"
foreach ($row in $test) {Write-Output "<p> $row </p>"}
Output :
<p> abc </p>
<p> def </p>
<p> ghi </p>
cls
$Path = 'C:\temp\test' #Path Directory
Grab a recursive list of all subfolders
$SubFolders = dir $Path -Recurse | Where-Object {$_.PSIsContainer} | ForEach-Object -Process {$_.FullName}
Iterate through the list of subfolders and grab the first file in each
ForEach ($Folder in $SubFolders)
{
$FullFileName = dir $Folder | Where-Object {!$_.PSIsContainer} | Sort-Object {$_.LastWriteTime} -Descending | Select-Object -First 1
For every file grab it's location and output the robocopy command ready for use
ForEach ($File in $FullFileName)
{
$FilePath = $File.DirectoryName
$FileName = $File.Name
write-output "$FilePath $FileName"
}
}

Get AD distinguished name

I'm trying to take input from a CSV file, which has a list of group names (canonical names) and get the Distinguished Name from it, then output to another CSV file. The code:
#get input file if passed
Param($InputFile)
#Set global variable to null
$WasError = $null
#Prompt for file name if not already provided
If ($InputFile -eq $NULL) {
$InputFile = Read-Host "Enter the name of the input CSV file (file must have header of 'Group')"
}
#Import Active Directory module
Import-Module -Name ActiveDirectory -ErrorAction SilentlyContinue
$DistinguishedNames = Import-Csv -Path $InputFile -Header Group | foreach-Object {
$GN = $_.Group
$DN = Get-ADGroup -Identity $GN | Select DistinguishedName
}
$FileName = "RESULT_Get-DistinguishedNames" + ".csv"
#Export list to CSV
$DNarray | Export-Csv -Path $FileName -NoTypeInformation
I've tried multiple solutions, and none have seemed to work. Currently, it throws an error because
Cannot validate argument on parameter 'Identity'. The argument is null. Supply a non-null argument and try the command again.
I tried using -Filter also, and in a previous attempt I used this code:
Param($InputFile)
#Set global variable to null
$WasError = $null
#Prompt for file name if not already provided
If ($InputFile -eq $NULL) {
$InputFile = Read-Host "Enter the name of the input CSV file(file must have header of 'GroupName')"
}
#Import Active Directory module
Import-Module -Name ActiveDirectory -ErrorAction SilentlyContinue
$DistinguishedNames = Import-Csv -Path $InputFile | foreach {
$strFilter = "*"
$Root = [ADSI]"GC://$($objDomain.Name)"
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher($root)
$objSearcher.Filter = $strFilter
$objSearcher.PageSize = 1000
$objsearcher.PropertiesToLoad.Add("distinguishedname") | Out-Null
$objcolresults = $objsearcher.FindAll()
$objitem = $objcolresults.Properties
[string]$objDomain = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
[string]$DN = $objitem.distinguishedname
[string]$GN = $objitem.groupname
#Get group info and add mgr ID and Display Name
$props = #{'Group Name'= $GN;'Domain' = $objDomain;'Distinguished Name' = $DN;}
$DNS = New-Object psobject -Property $props
}
$FileName = "RESULT_Get-DistinguishedNames" + ".csv"
#Export list to CSV
$DistinguishedNames | Sort Name | Export-Csv $FileName -NoTypeInformation
The filter isn't the same one I was using here, I can't find the one I was using, the I currently have is a broken attempt.
Anyway, the main issue I was having is that it will get the group name, but search for it in the wrong domain (it wouldn't include Organizational Units) which caused none of them to be found. When I search for a group in PowerShell though (using Get-ADGroup ADMIN) they show up with the correct DN and everything. Any hints or code samples are appreciated.
You seemingly miss the point of $variable = cmdlet|foreach {script-block} assignment. The objects to assign to $variable should be returned (passed through the script block) in order to end up in $variable. Both your main loops contain the structure of the line $somevar=expectedOutput where expectedOutput is either a New-Object psobject or Get-ADGroup call. The assignment to $someVar suppresses the output, so that the script block does not have anything to return, and $variable remains null. To fix, do not prepend the call that should return an object into outside variable with an assignment.
$DistinguishedNames = Import-Csv -Path $InputFile -Header Group | foreach-Object {
$GN = $_.Group
Get-ADGroup -Identity $GN | Select DistinguishedName # drop '$DN=`
}
$DistinguishedNames | Export-CSV -Path $FileName -NoTypeInformation
The same issue with the second script.

Import-Csv TrimEnd Column Header

I need import a CSV and run it through a foreach loop. I want to trim the end on the column header DeviceName to avoid any potential issues. I have tried the following but it is not working as expected.
$Import = Import-CSV $csv
foreach ($i in ($import.DeviceName).TrimEnd())
{do something}
Any help? Thank you!
If you need to change both the header and the content in the column for devicename which has spaces I have come up with this forgiving code.
$csvData = import-csv $csv
$properties = $csvData[0].psobject.Properties.name
$csvHeader = "`"$(($properties | ForEach-Object{$_.Trim()}) -join '","')`""
$deviceHeader = $properties -match "DeviceName"
$csvHeader
$csvHeader | Set-Content $file
$csvData | ForEach-Object{
$_.$deviceHeader = ($_.$deviceHeader).trim()
$_
} | ConvertTo-Csv -NoTypeInformation | Select-Object -Skip 1 | Add-Content $file
What this does is read in the CSV like normal. Parse the property names of the object in the order they appear. We find the one that has DeviceName no matter how many spaces (if there is more that one you could have a problem). Keep that so we can use it to call the correct property of each "row".
Export the new cleaned header to the file. Then we go through each "row" removing all the leading and trailing space from the DeviceName. Once that is done write back the CSV to the original file.
The best solution would be to tell the other team to fix their generation procedure. However, if for some reason that's not an option, I'd recommend pre-processing the file before you import it as a CSV.
$filename = 'C:\path\to\your.csv'
(Get-Content $filename -Raw) -replace '^(.*DeviceName)[ ]*(.*)', '$1$2' |
Set-Content $filename
Reading the file as a single string (-Raw) and anchoring the expression at the beginning of the string (^) ensures that only the column title is replaced.
For large input files you may want to consider a different approach, though, since the above reads the entire file into memory before replacing the first line.
$infile = 'C:\path\to\input.csv'
$outfile = 'C:\path\to\output.csv'
$firstLine = $true
Get-Content $infile | % {
if ($firstLine) {
$_ -replace '(DeviceName)[ ]*', '$1'
$firstLine = $false
} else {
$_
}
} | Set-Content $outfile
Thinking about it some more and taking inspiration from a comment to #Zeek's answer, you could also extract the headers first and then convert the rest of the file.
$infile = 'C:\path\to\input.csv'
$outfile = 'C:\path\to\output.csv'
$header = (Get-Content $infile -First 1) -split '\s*,\s*'
Get-Content $infile |
select -Skip 1 |
ConvertFrom-Csv -Header $header |
Export-Csv $outfile -NoType
Is this all you're trying to do? This will give you a collection of objects imported from your csv file but trim the end of the DeviceName property on each object.
$items = Import-CSV -Path $csv
$items.ForEach({ $_.DeviceName = $_.DeviceName.TrimEnd() })