I have this code that I am running from powershell. When I run it without the export-csv i get all the folder names on the screen.
dir | select -expand fullname | % { ($_ -split '\')[7]
But if I add | export-csv c:\test.txt then I see following in the file not the folder name I expected just like I see it on the screen.
#TYPE System.String
"Length"
"13"
"18"
"20"
"22"
"29"
"21"
"24"
"11"
"17"
"20"
"20"
Export-Csv exports a table of object properties and their values. Since your script is producing string objects, and the only property they have is length, that's what you got.
If you just want to save the list, use Out-File or Set-Content instead of Export-Csv.
The previous answer does work, but what if someone was looking to output it into a CSV file.
This does NOT work:
$str_list = #('Mark','Henry','John')
$str_list | Export-Csv .\ExportStrList.csv -NoType
Because Export-Csv takes Objects and outputs properties. The only properties for a String[ ] is Length, so the CSV file only contains Lengths.
To fix this we need to change the String[ ] into an Object[ ]. The simplest way is with Select-Object.
Put each String into the Name property of a new Object[ ], like this:
$str_list = #('Mark','Henry','John')
$obj_list = $str_list | Select-Object #{Name='Name';Expression={$_}}
$obj_list | Export-Csv .\ExportStrList.csv -NoType
Just to re-iterate, Select-Object outputs a custom PSObject that can easily be manipulated. This is very powerful information, use it wisely.
This worked for me:
$data = #()
$row = New-Object PSObject
$row | Add-Member -MemberType NoteProperty -Name "name1" -Value "Test"
$row | Add-Member -MemberType NoteProperty -Name "name2" -Value 2
$data += $row
$data | Export-Csv "Text.csv" -NoTypeInformation
This is another way to handle this issue:
Out-File outputs by default
Define the master array list
$MASTER_ARRAY_LIST = [System.Collections.ArrayList]#()
Define the output filename
$OutputFilename="C:\TEMP\MyOutputFile.csv"
ForEach ( $Something in $List_of_Somethings) {
$CURRENT_RECORD_DETAILS = New-Object PSObject -Property #{'name'=$($Something.Name);'fullname'=$($Something.FullName);'id'=$($Something.ID)}
$MASTER_ARRAY_LIST.Add( $CURRENT_RECORD_DETAILS ) > $null
}
$MASTER_ARRAY_LIST.ToArray() | Select-Object -Property name,fullname,id | Export-Csv -Path $OutputFilename -NoTypeInformation
$test = #("test1","test2","test3")
$test | export-csv "firstTry.csv"
#We see that this fails. So here is how to to do it with the desired results
foreach ($item in $test) {
[ pscustomobject]#{ ResultColumn = $item } | Export-Csv -Path ./secondTry.csv -NoTypeInformation -Append
}
$output |Select-Object * | Export-Csv 'h:\filename.csv' -NoTypeInformation
Related
I have a Powershell script, which collects the size of a backup, and exports it to CSV, I would like to know if it is possible that it could be added to the next csv column, or an excel.
I've been looking at the documentation, because I think it looks better on an excel, but I can't add one more column, I always believe it from scratch.
$today = (get-date).Date
$backup = Get-VBRBackup | where {$_.info.jobname -eq "A. ProduccionInterna.Infraestructura Backup Copy"}
if ($backup) {
$backup.GetAllStorages() | where {$_.CreationTime.Date -eq $today} | select {$_.PartialPath}, {$_.Stats.BackupSize/1GB} |
export-csv -Path C:\Users\acepero\Documents\test.csv -NoTypeInformation -Delimiter ';'
}
UPDATE
I have managed to create new columns once, then it gives an error:
Select-Object : The property cannot be processed because the property "{$_.PartialPath}, {$_.Stats.BackupSize/1GB} , {$Session.BackupStats.DedupRatio} ,
{$Session.BackupStats.CompressRatio}" already exists.
The code now has this form
$today = (get-date).Date
$backup = Get-VBRBackup | where {$_.info.jobname -eq "A. ProduccionInterna.Infraestructura Backup Copy"}
if ($backup) {
$backup.GetAllStorages() | where {$_.CreationTime.Date -eq $today} | select {$_.PartialPath}, {$_.Stats.BackupSize/1GB} , {$Session.BackupStats.DedupRatio} , {$Session.BackupStats.CompressRatio}
(Import-Csv "C:\Users\acepero\Documents\test.csv") |
Select-Object *, {{$_.PartialPath}, {$_.Stats.BackupSize/1GB} , {$Session.BackupStats.DedupRatio} , {$Session.BackupStats.CompressRatio}} |
Export-csv -Path C:\Users\acepero\Documents\test.csv -NoTypeInformation #-Delimiter ';'
}
When you take output from a command and pipe it through select, you are creating an output object, which has the selected values as properties. Here is an example using the Get-ChildItem command:
$result = Get-ChildItem C:\Temp | select Name, Length
The $result array contains objects which have the "Length" and "Name" NoteProperties. When you pipe that object to Export-CSV, it creates one column for each Property/NoteProperty the object has. In order to 'add a column to the CSV', all you need to do is add a NoteProperty to the object. You can do that with the Add-Member cmdlet, like this:
$result | Add-Member -MemberType NoteProperty -Name 'ColumnName' -Value 'ColumnValue'
Be careful how you do this. If $result is a single object, this command will add the NoteProperty/Value pair to that object. If $result is an array of objects, it will add that NoteProperty/Value pair to all objects held in the array. If you need to assign different values to each object, you'll need to iterate through the array:
ForEach ($res in $result)
{
$thisvalue = '' #Assign specific value here
$res | Add-Member -MemberType NoteProperty -Name 'ColumnName' -Value $thisvalue
}
I hope this helps you. If it does, please don't forget to accept the answer.
So I'm trying to process CSV files, then giving the output new name. I can do it with one file by explicitly specifying the file name. But is there a way / wildcard I can use to make the script to process multiple files at the same time? Let's just say I want to process anything with .csv as an extension. Here's my script that's used to process a specific file
$objs =#();
$output = Import-csv -Path D:\TEP\FilesProcessing\Test\file1.csv | ForEach {
$Object = New-Object PSObject -Property #{
Time = $_.READ_DTTM
Value = $_.{VALUE(KWH)}
Tag = [String]::Concat($_.SUBSTATION,'_',$_.CIRCUITNAME,'_',$_.PHASE,'_',$_.METERID,'_KWH')
}
$objs += $Object;
}
$objs
$objs | Export-CSv -NoTypeInformation D:\TEP\FilesProcessing\Test\file1_out.csv
You can combine Get-ChildItem and Import-Csv.
Here's an example that specifies different input and output directories to avoid name collisions:
$inputPath = "D:\TEP\FilesProcessing\Test"
$outputPath = "D:\TEP\FilesProcessing\Output"
Get-ChildItem (Join-Path $inputPath "*.csv") | ForEach-Object {
$outputFilename = Join-Path $outputPath $_.Name
Import-Csv $_.FullName | ForEach-Object {
New-Object PSObject -Property #{
"Time" = $_.READ_DTTM
"Value" = $_.{VALUE(KWH)}
"Tag" = "{0}_{1}_{2}_{3}_KWH" -f $_.SUBSTATION,$_.CIRCUITNAME,$_.PHASE,$_.METERID
}
} | Export-Csv $outputFilename -NoTypeInformation
}
Note that there's no need for creating an array and repeatedly appending it. Just output the custom objects you want and export afterwards.
Use the Get-Childitem and cut out all the unnecessary intermediate variables so that you code it in a more Powershell type way. Something like this:
Get-CHhilditems 'D:\TEP\FilesProcessing\Test\*.csv' | % {
Import-csv $_.FullName | % {
New-Object PSObject -Property #{
Time = $_.READ_DTTM
Value = $_.{VALUE(KWH)}
Tag = '{0}_{1}_{2}_{3}_KWH' -f $_.SUBSTATION, $_.CIRCUITNAME, $_.PHASE, $_.METERID
}
} | Export-CSv ($_.FullName -replace '\.csv', '_out.csv') -NoTypeInformation
}
The Get-ChildItem is very useful for situations like this.
You can add wildcards directly into the path:
Get-ChildItem -Path D:\TEP\FilesProcessing\Test\*.csv
You can recurse a path and use the provider to filter files:
Get-ChildItem -Path D:\TEP\FilesProcessing\Test\ -recurse -include *.csv
This should get you what you need.
$Props = #{
Time = [datetime]::Parse($_.READ_DTTM)
Value = $_.{VALUE(KWH)}
Tag = $_.SUBSTATION,$_.CIRCUITNAME,$_.PHASE,$_.METERID,'KWH' -join "_"
}
$data = Get-ChildItem -Path D:\TEP\FilesProcessing\Test\*.csv | Foreach-Object {Import-CSV -Path $_.FullName}
$data | Select-Object -Property $Props | Export-CSv -NoTypeInformation D:\TEP\FilesProcessing\Test\file1_out.csv
Also when using Powershell avoid doing these things:
$objs =#();
$objs += $Object;
I have a well-formed CSV file that I want to read, reformatting some values while doing so. For some reason the code below does not work ($csv variable ends up being empty):
$csv = Import-Csv "result.log" -Delimiter "|" | ForEach-Object {
$_.PSObject.Properties.Value | ForEach-Object {
if ($_ -like '*---*') { $_ = "" }
}
}
What am I doing wrong?
Your result is blank because you aren't returning anything to the pipeline (you are just changing the value of one or more properties but then not outputting them).
There might be a simpler solution but I think this achieves what you want:
$CSV = Import-Csv "result.log" -Delimiter "|" | Foreach-Object {
$Output = New-Object -TypeName PSObject
$_.PSObject.Properties | Foreach-Object {
If ($_.Value -like '*---*') { $_.Value = '' }
$Output | Add-Member -Name $_.Name -Value $_.Value -MemberType NoteProperty
}
$Output
}
This performs the following for each row of the CSV:
creates a new empty PowerShell object
loops through the properties of the CSV, blanking ones that include --- and then uses Add-Member to add those properties to our object
outputs the new object to the standard pipeline
The result of this goes to the $CSV variable which you then could output as CSV via Export-CSV (or you could skip putting it in the variable and use Export-CSV on the end of the outer ForEach-Object).
Just want to ask how to Export the data in existing CSV file in new column. I have this following code.
$Ex=Compare-Object $ImportWin7 $Importafipd1 -includeequal
$Ex | Select-Object SideIndicator | Export-Csv -Append -Force -NoTypeInformation "C:\NotBackedUp\EndpointAudit\Win7machinetest2.csv"
but it appears that the Data from $EX was appended not on the first row of the column.
You can't just add an additional column to existing csv document. You would want to recreate it again with number of columns you need. Like so:
$ExistingCSV = Import-Csv "C:\NotBackedUp\EndpointAudit\Win7machinetest2.csv"
$Ex=Compare-Object $ImportWin7 $Importafipd1 -includeequal | Select-Object SideIndicator
$obj = #()
$i = 0
foreach ($row in $ExistingCSV)
{
$item = New-Object PSObject -ArgumentList $row
$item | Add-Member -MemberType NoteProperty extra_column -Value $Ex[$i]
$obj += $item
$i++
}
$obj | Export-Csv -Append -Force -NoTypeInformation "C:\NotBackedUp\EndpointAudit\Win7machinetest2.csv"
I have a script like the following:
$in_file = "C:\Data\Need-Info.csv"
$out_file = "C:\Data\Need-Info_Updated.csv"
$list = Import-Csv $in_file
ForEach ( $user in $list ) {
$zID = $user.zID
ForEach-Object {
Get-QADUser -Service 'domain.local' -SearchRoot 'OU=Users,DC=domain,DC=local' -SizeLimit 75000 -LdapFilter "(&(objectCategory=person)(objectClass=user)(PersonzID=$zID))" | Select-Object DisplayName,samAccountName,#{Name="zID";expression={$zID}} | Export-Csv $out_file -NoTypeInformation -Force
}
}
However, I am not able to get it to output all of the results to the $out_file since it does not seem to append the data to the csv file.
Is there a way to make this append the data to a file?
Convert the foreach loop into a foreach-object, and move the export-csv to outside the outer foreach object so that you can pipe all the objects to the export-csv.
Something like this (untested):
$list | ForEach {
$zID = $_.zID
ForEach-Object {
Get-QADUser -Service 'domain.local' -SearchRoot 'OU=Users,DC=domain,DC=local' -SizeLimit 75000 -LdapFilter "(&(objectCategory=person)(objectClass=user)(PersonzID=$zID))" | Select-Object DisplayName,samAccountName,#{Name="zID";expression={$zID}}
}
} | Export-Csv $out_file -NoTypeInformation -Force
As Sune mentioned, PowerShell v3's Export-Csv has an Append flag but no character encoding protection. manojlds is correct, since your code is writing all new data to a new CSV file.
Meanwhile, you can append data to a CSV by:
Convert the objects to CSV with ConvertTo-Csv
Strip the header —and type information if necessary— and collect the
CSV data only
Append the new CSV data to the CSV file through Add-Content or
Out-File, be sure to use same character encoding
Here is a sample:
1..3 | ForEach-Object {
New-Object PSObject -Property #{Number = $_; Cubed = $_ * $_ * $_}
} | Export-Csv -Path .\NumTest.csv -NoTypeInformation -Encoding UTF8
# create new data
$newData = 4..5 | ForEach-Object {
New-Object PSObject -Property #{Number = $_; Cubed = $_ * $_ * $_}
} | ConvertTo-Csv -NoTypeInformation
# strip header (1st element) by assigning it to Null and collect new data
$null, $justData = $newData
# append just the new data
Add-Content -Path .\NumTest.csv -Value $justData -Encoding UTF8
# create more new data, strip header and collect just data
$null, $data = 6..9 | ForEach-Object {
New-Object PSObject -Property #{Number = $_; Cubed = $_ * $_ * $_}
} | ConvertTo-Csv -NoTypeInformation
# append the new data
Add-Content -Path .\NumTest.csv -Value $data -Encoding UTF8
# verify
Import-Csv .\NumTest.csv
# clean up
Remove-Item .\NumTest.csv
-append is broken in PowerShell v2.0. You can use Dmitry Sotikovs workaround instead: http://dmitrysotnikov.wordpress.com/2010/01/19/export-csv-append/
I would however recommend manojlds excellent solution!
After version 3 you can use:
Export-Csv $out_file -append -notypeinformation -encoding "unicode"