Powershell, how obtain a csv by column with a pscustomobject or ordered? - string

Being a beginner in Powershell, I have a problem that I can't solve. I get the average of different CSV files as a string with the following code:
# recovery of the list of csv files present in the folder "folder_1".
$files=(Get-ChildItem -path "C:\folder_1\" -Recurse -Include *.csv)
#loop to read each file and average the variables "PRESS_CELL" and "PRESS_DELTA
foreach($file in $files){
$varTemp = #((Get-Content $file | ConvertFrom-Csv | Measure-Object "PRESS_CELL","PRESS_DELTA" -Average | Export-Csv -Path "C:\folder_1\Alias.csv" -NoTypeInformation -Append))
Write-Host $varTemp
}
#added an increment to sort the data (averages)
$vartemp2 = Import-CSV "C:\folder_1\Alias.csv" | Select *,LINENUMBER | ForEach-Object -Begin { $Line = 1 } {
$_.LineNumber = $Line++
$_
} | Export-CSV "C:\folder_1\Alias2.csv" -NoTypeInformation
Write-Host $vartemp2
# sort data by "property" and by "LINENUMBER"
$vartemp3 = Import-Csv "C:\folder_1\Alias2.csv"
$vartemp3 | % { $_.LINENUMBER = [int]$_.LINENUMBER }
$vartemp3 | Sort-Object -Property #{ Expression = 'Property'; Ascending = $true }, #{ Expression = 'LINENUMBER'; Ascending = $true } |
Format-Table -Property "Average","Property","LINENUMBER"
# groups the values obtained in a table/customobject and export it to csv by column ?
$fields = [ordered]#{
PRESS_CELL = $vartemp3 | ? property -like *PRESS_CELL* | Select -ExpandProperty Average
PRESS_DELTA = $vartemp3 | ? property -like *PRESS_DELTA* |Select -ExpandProperty Average
}
$fields | export-csv C:\1_ICOS_data\Alias4.csv -Append ##DOESN'T WORK
[result][1]
However, I would like to export the result as a CSV table (1 column per result with PRESS_CELL and PRESS_DELTA as headers. When I use the pipeline :
| export-csv C:\temp\alias.csv -Append
I get a result :
With "ordered"
"System.Collections.Specialized.OrderedDictionary+OrderedDictionaryKeyValueCollection","System.Collections.Specialized.OrderedDictionary+OrderedDictionaryKeyValueCollection","False","System.Object","False"
And with pscustomobject :
System.Object[],"System.Object[]"

Add -NoTypeInformation to export-csv command like that
$fields = [ordered]#{
PRESS_CELL = $vartemp3 | ? property -like *PRESS_CELL* | Select -ExpandProperty Average
PRESS_DELTA = $vartemp3 | ? property -like *PRESS_DELTA* |Select -ExpandProperty Average
}
#Or:
$fields = [pscustomobject]#{
PRESS_CELL = $vartemp3 | ? property -like *PRESS_CELL* | Select -ExpandProperty Average
PRESS_DELTA = $vartemp3 | ? property -like *PRESS_DELTA* |Select -ExpandProperty Average }
$fields |export-csv "c:\fields.csv" -Append -NoTypeInformation

Related

Powershell - cut domain name from FQDN

I would like to list all Session Hosts in all Collections, convert to string. I get this with:
$SHs = (Get-RDSessionCollection -ConnectionBroker $CB | Select-Object -Property collectionname | ForEach-Object -Process { Get-RDSessionHost -ConnectionBroker $CB -CollectionName $_.collectionname }) |select SessionHost |Out-String
Output:
SessionHost
-----------
SH1.contoso.com
SH2.contoso.com
SH3.contoso.com
Now I would like cut domain name .contoso.com from fqdn.
foreach ($SH in $SHs){
$SH = $SH.Substring(0,$SH.Length-12)
$SH
}
but the output still:
SessionHost
-----------
SH1.contoso.com
SH2.contoso.com
SH3.contoso.com
Desired Output is:
SH1
SH2
SH3
Edit: I tried followings codes (thx for help):
$SH = ($SH -split "\.")[0]
and
$SH = ($SH -split '\.' | Select -first 1) -join '.'
and I receive only :
SH01
Thank you for any help!
Without having a terminal server to test this should work actually:
$SHs = (
Get-RDSessionCollection -ConnectionBroker $CB |
Select-Object -Property collectionname |
ForEach-Object -Process {
Get-RDSessionHost -ConnectionBroker $CB -CollectionName $_.collectionname
}
) |
Select-Object -Property SessionHost
foreach ($SH in $SHs.SessionHost) {
($SH -split "\.")[0]
}

Code to grab file data into PSOObject and sort by LastWriteTime

I am looking to recursively grab a list of recently modified files under two network drives, sort them in descending date order, and make some edits to the CSV file to tidy the list for Excel
I have cobbled the code below from a number of sources (I am a powershell beginner) and it is now doing what I need (i.e. producing a list).
I need help in going a step further, I cannot sort the resultant CSV file by file last write time date, is this because my array is expecting text rather than a numeric field?
I also am returning the domain name as well as the file owner with ((Get-ACL $_.FullName).Owner). I tried using Replace to cut down the string, but had no luck with this approach.
$arr = #()
$days_to_check=$(Get-Date).AddDays(-28)
$items = #(Get-ChildItem '\\ND\dir 1\*.*' -Recurse -ErrorAction SilentlyContinue | where { $_.LastWriteTime -gt $days_to_check})
$items += #(Get-ChildItem '\\ND\dir 1\*.*' -Recurse -ErrorAction SilentlyContinue |
where { $_.LastWriteTime -gt $days_to_check})
$items | Foreach {
$obj = New-Object PSObject -prop $hash
$obj | Add-Member NoteProperty FullName $_.FullName
$obj | Add-Member NoteProperty Directory $_.Directory
$obj | Add-Member NoteProperty Name $_.Name
$obj | Add-Member NoteProperty LastTime $_.LastWriteTime
$obj | Add-Member NoteProperty Owner ((Get-ACL $_.FullName).Owner)
$arr += $obj
}
$arr | Format-List
$arr | Sort-Object -Property LastTime -Descending
$arr | Export-CSV -notypeinformation C:\temp\filenamesFO.csv
CSV file sorted by date field
You did sort your array in the output but that's all you did.
If you want to actually export it that way, you have to assign the sort to $arr
Replace
$arr | Sort-Object -Property LastTime -Descending
with
$arr = $arr | Sort-Object -Property LastTime -Descending
You can remove the Owner domain using the following Replace -replace '(.*\\)(.*)','$2'
Here's a complete example implementing the changes mentionned above.
$arr = new-object -TypeName 'System.Collections.Generic.List[PSObject]'
$days_to_check=$(Get-Date).AddDays(-28)
$items = #(Get-ChildItem '\\ND\dir 1\*.*' -Recurse -ErrorAction SilentlyContinue | where { $_.LastWriteTime -gt $days_to_check})
$items += #(Get-ChildItem '\\ND\dir 1\*.*' -Recurse -ErrorAction SilentlyContinue |
where { $_.LastWriteTime -gt $days_to_check})
Foreach ($item in $items) {
$obj = [PSCustomObject]#{
FullName = $item.FullName
Directory = $item.Directory
Name = $item.Name
LastTime = $item.LastWriteTime
Owner = (Get-ACL $item.FullName).Owner -replace '(.*\\)(.*)','$2'
}
$arr.add($obj)
}
$arr = $arr | Sort-Object -Property LastTime -Descending
#$arr | Format-List
$arr | Export-CSV -notypeinformation C:\temp\filenamesFO.csv
I made some additional changes:
Instead of using an array, I used a List of PSObject. If you have a lot of files, the processing time will be improved in comparison with an array.
I used the PSCustomObject declaration just to show an alternative to all those Add-member. I find it cleaner but it is up to you in the end.

Display the difference of Excel columns with PowerShell

I would like to get the difference in the columns in as a table but I only can do a comparison with two columns and it doesn't display all the columns. I need to see in which column the cell is not present in the first column.
The file:
ComputerName OtherComputerName OtherComputer AndAgain
infra-1 infra-852 infra-2 infra-99
infra-98 infra-85 infra-44 infra-23
infra-5 infra-8 infra-1 infra-1
infra-2 infra-55 infra-8 infra-70
infra-62 infra-5 infra-852 infra-5
The current result:
ComputerName OtherComputerName OtherComputer AndAgain
------------ ----------------- ------------- --------
I would like to get this as result in PowerShell:
ComputerName OtherComputerName OtherComputer AndAgain
------------ ----------------- ------------- --------
infra-1 infra-852 infra-99
infra-98 infra-85 infra-44 infra-23
infra-5 infra-8
infra-2 infra-55 infra-8 infra-70
infra-62 infra-852
Edit
I have some errors too when I run this code.
The script:
$csv = Import-Csv .\test1.csv -Delimiter ';'
$ref = #($csv.ComputerName)
foreach ($row in $csv) {
foreach ($col in 'OtherComputerName', 'OtherComputer', 'AndAgain') {
if ($ref -contains $row.$col) { $row.$col = '' }
}
}
$table = #()
$file = Get-Content .\test1.csv
$file = $file -replace(" "," ")
$file = $file -replace(" "," ")
$file = $file -replace(" "," ")
$file = $file -replace(" - "," ")
[string[]]$a = Import-Csv '.\test1.csv' | select -Expand ComputerName
[string[]]$b = Import-Csv '.\test1.csv' | select -Expand OtherComputerName
[string[]]$c = Import-Csv '.\test1.csv' | select -Expand OtherComputer
[string[]]$d = Import-Csv '.\test1.csv' | select -Expand AndAgain
$b | ? {$a -notcontains $_}
$c | ? {$a -notcontains $_}
$d | ? {$a -notcontains $_}
foreach ($line in $file) {
$lineb = $line -split(" ")
$obj = New-Object PSObject
$obj | Add-Member -Name "ComputerName" -MemberType NoteProperty -Value $lineb[1]
$obj | Add-Member -Name "OtherComputerName" -MemberType NoteProperty -Value $lineb[1]
$obj | Add-Member -Name "OtherComputer" -MemberType NoteProperty -Value $lineb[2]
$obj | Add-Member -Name "AndAgain" -MemberType NoteProperty -Value $lineb[3]
$table += $obj
}
$table | ft -AutoSize
You need to read the values of the first column into an array, compare the values of the other columns against that array, and clear matching fields:
$csv = Import-Csv .\test1.csv -Delimiter ';'
$ref = #($csv | Select-Object -Expand ComputerName)
foreach ($row in $csv) {
foreach ($col in 'OtherComputerName', 'OtherComputer', 'AndAgain') {
if ($ref -contains $row.$col) { $row.$col = '' }
}
}

Powershell+Export-Excel module

I use Export-Excel module for Powershell. I try to get results of "foreach" from 2 links in a table. But finally i have only one link in the table(only second one). "Out-File" has "=Append",that appends to a file. Maybe there is something like this for "Export-Excel"?
[Reflection.Assembly]::LoadFrom("C:\selenium\net40\WebDriver.dll")
$url = Get-Content D:\dww.txt
$ie = New-Object OpenQA.Selenium.PhantomJS.PhantomJSDriver
foreach ($u in $url) {
$ie.Navigate().GoToUrl($u)
$title = $ie.FindElementByXPath("//h1[contains(#class, 'fullstory')]")
$fullstory = $ie.FindElementByClassName("comment")
$tracklist = $ie.FindElementByXPath("//*[contains(#id,'news-id')]")
$links = $ie.FindElementByXPath("//*[contains(#class, 'link')]")
$img = $ie.FindElementsByclassname("stars").findelementbytagname("img").getattribute("src")
$h = Write-Output Стиль,Формат,"Год выпуска",Размер,"Название альбома",Исполнитель,Треклист,Ссылка,Обложка
$data = ($fullstory.text).split("`n") -replace ": ","=" | Where {$_.Trim()} | Out-String | ConvertFrom-StringData | Foreach {[pscustomobject]$_} | Select $h
$data.Ссылка = $links.text
$data.Треклист = $tracklist.text
$data.Обложка = $img
$data | Export-Excel d:\filedark2.xlsx -AutoSize
Write-Host $u " - выгружено"
}
$ie.Quit()
if you're only using export-excel to save to a new excel document, you might try just exporting to csv using -append and converting to excel afterward with this
https://github.com/gangstanthony/PowerShell/blob/master/Save-CSVasExcel.ps1
...
$data | Export-Csv d:\filedark2.csv -Append -NoTypeInformation
...
}
Save-CSVasExcel d:\filedark2.csv
...

Export-CSV only gets the "Length"

when I try to export to a CSV list, I only get all number for "Length"
.Count property until the split point is reached, then split the CSV array to a new file with a new name that will be used from this point on. What might be the issue?
$RootFolder = Get-Content "c:\DRIVERS\myfile.txt"
foreach ($arrayOfPaths in $RootFolder){
$csv = $arrayofPaths -replace '^\\\\[^\\]+\\([^\\]+)\\([^\\]+).*', 'C:\output\Company_name_${1}_${2}.csv'
$csvIndex = 1
$maxRows = 1000000
$rowsLeft = $maxRows
Get-ChildItem $arrayOfPaths -Recurse | Where-Object {$_.mode -match "d"} | ForEach-Object {
#$csv = $_.FullName -replace '^\\\\[^\\]+\\([^\\]+)\\([^\\]+).*', 'C:\output\Company_name_${1}_${2}.csv'# <- construct CSV path here
$path = $_.FullName
$thisCSV = Get-Acl $path | Select-Object -Expand Access |
Select-Object #{n='Path';e={$path}}, IdentityReference, AccessControlType,
FileSystemRights |
ConvertTo-Csv
if ($thisCSV.count -lt $rowsLeft) {
$thisCSV | Export-Csv $csv -append -noType
$rowsLeft -= $thisCSV.count
} else {
$thisCSV[0..($rowsLeft - 1)] | Export-Csv $csv -append -noType
$csvIndex++
$csv = $csv -replace '\.csv$', "$csvIndex.csv"
if ($thisCSV.count -gt $rowsLeft) {
$thisCSV[$rowsLeft..($thisCSV.count - 1)] | Export-Csv $csv -append -noType
}
$rowsLeft = $maxRows - ($thisCSV.count - $rowsLeft)
}
}
}
Export-CSV is built to take PSCustomObjects as input, not lines of text.
$thisCSV = Get-Acl $path | Select-Object -Expand Access |
Select-Object #{n='Path';e={$path}}, IdentityReference, AccessControlType,
FileSystemRights |
ConvertTo-Csv
The output of this line will be something like:
#TYPE Selected.System.Security.AccessControl.FileSystemAccessRule
"Path","IdentityReference","AccessControlType","FileSystemRights"
"c:\test","BUILTIN\Administrators","Allow","FullControl"
At least three lines, an array of string. What properties does an array of string have?
PS C:\> 'a','b' | Get-Member -MemberType Property
TypeName: System.String
Name MemberType Definition
---- ---------- ----------
Length Property int Length {get;}
Length. The only property you see in the CSV, because Export-CSV is exporting all the properties, and that's the only property.
Fix: Remove | ConvertTo-CSV from the Get-ACL line, leave your custom objects as custom objects and let the export handle converting them.
(This should also fix the counting, because it's not counting 3+ lines of text while trying to export 1+ line of data every time).

Resources