I have the following powershell script:
$grouped_TPR_Test1=Import-Csv c:\TPR.csv | group UPC -AsHashTable -AsString
Import-Csv c:\HQ.csv | foreach{
$tpr_Sales=($grouped_TPR_Test1."$($_.UPC)" | foreach {$_.TPR_Sales}) -join ","
$_ | Add-Member -MemberType NoteProperty -Name TPR_SALES -Value $tpr_Sales -PassThru
} | Export-Csv -NoTypeInformation c:\HQ_TPR_sales.csv
It finds/matches the UPC value in file c:\TPR.csv with the same value in this file. c:\HQ.csv and outputs the corresponding sales data from to a 3rd file that includes all fields in c:\HQ.csv as well as the additional ones that match on UPC from c:\TPR.csv
This works.
However, I am not sure how to add a second field to check ("Zone", to narrow down the results that are sent to the 3rd output file. Both files have the zone field as well.
I read a bit on this and an array seems better suited for multiple criteria, rather than a hashtable, but I'm not having much luck.
c:\HQ.csv looks essentially like this:
UPC ZONE column1 column2 column3
1234567890123 3 blah1 blah2 blah3
c:\TPR.csv looks essentially like this:
UPC ZONE sales
1234567890123 3 5.00
1234567890123 2 4.00
3210987654321 2 3.00
Any help is appreciated.
Thanks!
You could simply just use WHERE-OBJECT on the resulting file to just pull out the zone(s) you are interested in:
Import-CSV c:\HQ_TPR_sales.csv | WHERE-OBJECT {$_.Zone -eq 2}
Or put the WHERE-OBJECT into your pipe before you export-csv:
... | ? {$_.Zone -eq 2} | Export-CSV ...
Related
$groups = Get-Content c:\devices.csv | Group {$_.Substring(0,3)}| %{$_.Group; ""}
AAAGroup1,192.168.1.1
AAAGroup1,192.168.1.2
BBBGroup2,192.168.2.1
BBBGroup2,192.168.2.2
CCCGroup3,192.168.3.1
CCCGroup3,192.168.3.2
I have searched far and wide and can only find solutions based on column selections To output the above data to either a separate variable per group or separate CSV file. Technically, there's a space in between each group in terms of a spare row, that's it as far as i can see.
$groups = Get-Content c:\devices.csv | Group {$_.Substring(0,3)}| %{$_.Group; ""}
ForEach ($Group in $Groups)...
Provided you have a file devices.csv with headers Device,IPv4
The following script will add a calculated property named Group you can use to sort, output to a table and -GroupBy or whatever.
## Q:\Test\2018\07\10\SO_51267179.ps1
$data = Import-Csv '.\devices.csv' |
Select-Object Device,IPv4,#{n='Group';e={$_.Device.Substring(0,3)}}
$data | Format-Table -GroupBy Group
Sample output
Group: AAA
Device IPv4 Group
------ ---- -----
AAAGroup1 192.168.1.1 AAA
AAAGroup1 192.168.1.2 AAA
...snip...
To output each group to it's own .csv
$data = Import-Csv '.\devices.csv' |
| Group-Object {$_.Device.Substring(0,3)}| ForEach-Object {
$_.Group | Export-Csv "$($_.Name).csv" -NoTypeInformation
}
Sample output:
> gc .\AAA.csv
"Device","IPv4"
"AAAGroup1","192.168.1.1"
"AAAGroup1","192.168.1.2"
I'm writing a windows powershell script to open/edit a text file.
It has many records and each record is sorted of comma-separated values (csv):
Steps I want to achieve:
Open the text files in a directory on Server A.
Edit the "Date" field with "Current Date" or other.
Save the same text file at the same location(folder).
Copying all the files to a new folder in different Server B.
I've just written this code snippet:
$path = "C:\PSFiles\Rec_File_001.txt"
$Filedata = Get-Content $path
$Record01 = $Filedata[0].split(",")
$Record01Date = $Record01[3]
$Record01CurrentDate = Get-Date -format yyMMdd
$Record01 -replace $Record01Date, $Record01CurrentDate
Set-Content $path
Please, any help on this?
You are having multiple questions here. I'll address the one that is presented in the title - replacing text in a text file.
The script:
# current date in a new format
$CurrentDate = Get-Date -format yyMMdd
#replace old format
Get-Content -ReadCount 500 -Path C:\PSFiles\Rec_File_001.txt | % {$_ -replace "(0[1-9]|1[012])\d{1,2}(0[1-9]|[12][0-9]|3[01])", "$CurrentDate"} | Set-Content -Path C:\PSFiles_output\Rec_File_001.txt
This takes regexp for date format Date(mmYYdd) and exchanges it for a new one. An option -ReadCount limits the number of lines that go via pipe at one time.
Import-CSV $Path -header text1, text2, text3, date, text5 |
Select text1, text2, text3, #{Name="Date"; Expression={Get-Date -format yyMMdd}}, text5 |
ConvertTo-Csv -NoTypeInformation |
Select-Object -Skip 1 |
Set-Content $Path
Or:
$data = Import-CSV $Path -header text1, text2, text3, date, text5
$data | ForEach {"Date" = Get-Date -format yyMMdd}
$data | ConvertTo-Csv -NoTypeInformation | Select-Object -Skip 1 | Set-Content $Path
Hopefully this helps. Run the following commands in powershell:
$(Get-Item ath/filename.extensionfilename).creationtime=$(get-date "2019-10-15T15:45:12.2723844+01:00")
$(Get-Item C:\temp\log\txt.log).creationtime=$(get-date "2019-10-15T15:45:12.2723844+01:00")
Here is an article from Microsoft that explains how to modify the timestamps of a file https://devblogs.microsoft.com/scripting/use-powershell-to-modify-file-access-time-stamps/
Below is a table from that article showing the attributes that involve time that you can modify.
+----------------+----------+-----------------+---------------------------+
| Name | Member | Type | Definition |
+----------------+----------+-----------------+---------------------------+
| CreationTime | Property | System.DateTime | CreationTime {get;set;} |
| LastAccessTime | Property | System.DateTime | LastAccessTime {get;set;} |
| LastWriteTime | Property | System.DateTime | LastWriteTime {get;set;} |
+----------------+----------+-----------------+---------------------------+
Here is my dilemma. I have a csv file with two columns
ID,FullFileName
1,Value1
1,Value2
1,Value3
2,Value1
2,Value2
3,Value1
4,Value1
5,Value1
5,Value2
The output I'm looking for is to get an exported csv with two columns in it ID, and FullFilename. The value in FullFileName will contain the matching joined values separated by a pipe delimiter.
But my output i'm trying to get the following:
ID,FullFilename
1,Value1|Value2|Value3
2,Value1|Value2
3,Value1
4,Value1
5,Value1|Value2
I'm not sure how to make powershell search the value in ID and take all of the results and yield them into a single concatenated value with a pipe separation. Any assistance on trying to search the array or join / concatenate array values would be greatly appreciated.
Group-Object is the useful cmdlet that can help you. Grouping the data by ID turns it into:
PS D:\> ipcsv .\t.csv | group id
Count Name Group
----- ---- -----
3 1 {#{ID=1; FullFileName=Value1}, #{ID=1; FullFileName=Value2}, #{ID=1; FullFileName=Value3}}
2 2 {#{ID=2; FullFileName=Value1}, #{ID=2; FullFileName=Value2}}
1 3 {#{ID=3; FullFileName=Value1}}
1 4 {#{ID=4; FullFileName=Value1}}
2 5 {#{ID=5; FullFileName=Value1}, #{ID=5; FullFileName=Value2}}
So you want the Name (= ID) and the Group property, just the FullFileName, joined up:
Import-Csv -Path c:\path\data.csv |
Group-Object -Property ID |
Select-Object #{Name='ID'; Expression={$_.Name}},
#{Name='FullFilename'; Expression={$_.Group.FullFileName -join '|'}} |
Export-Csv -Path C:\Path\out.csv -NoTypeInformation
$InFile = '.\Sample.csv'
$OutFile= '.\New.csv'
$Csv = Import-Csv $InFile | Group-Object ID | ForEach-Object{
[pscustomobject]#{
ID=$_.Name
FullFileName=$_.Group.FullFileName -join '|'
}
}
$Csv
"----------"
$Csv | Export-Csv $OutFile -NoTypeInformation
Get-Content $OutFile
Sample output:
ID FullFileName
-- ------------
1 Value1|Value2|Value3
2 Value1|Value2
3 Value1
4 Value1
5 Value1|Value2
----------
"ID","FullFileName"
"1","Value1|Value2|Value3"
"2","Value1|Value2"
"3","Value1"
"4","Value1"
"5","Value1|Value2"
Edit Just saw you wanted the pipe as delimiter.
Did my best but was to late, anyway here is the code
Instead of Group-Object i am using a HashTable, i find it easy to work with when my data comes from multiple sources.
$CSV = Import-Csv -Delimiter ',' -Path "$env:TEMP\testfolder\csv.txt" #can be .csv or whatever.
$HastTable = #{}
Foreach ($Line in $CSV) {
if (!$HastTable["$($Line.ID)"]) {
$HastTable["$($Line.ID)"] = $Line
}
else {
$HastTable["$($Line.ID)"].FullFileName += "|$($Line.FullFileName)"
}
}
$HastTable.Values | Export-Csv -Delimiter ',' -NoTypeInformation -Path "$env:TEMP\testfolder\newcsv.txt" #can be .csv or whatever.
I'm currently having a bit of trouble with my current project. I have two arrays - the first array contains reference values for disk size:
$RequiredDisks0 = New-Object System.Object
$RequiredDisks0 | Add-Member -Type NoteProperty -Name "DeviceID" -Value "C:"
$RequiredDisks0 | Add-Member -Type NoteProperty -Name "SizeGB" -Value "80"
The second array contains the disk information of the underlying system:
$SystemDisks = Get-WmiObject Win32_LogicalDisk |
Where {$_.DriveType -eq 3} |
select DeviceID,
#{Name="Size(GB)";Expression={[decimal]("{0:N0}" -f ($_.Size/1gb))}}
What I would like to do, is check the given array against the reference array to see if any given disks are smaller than required. I've found out that I can compare the arrays by using
Compare-Object -ReferenceObject $RequiredDisks -DifferenceObject $SystemDisks -Property SizeGB,DeviceID
And I indeed receive the differences as follows:
SizeGB DeviceID SideIndicator
------ -------- -------------
99 C: =>
15 H: =>
100 I: =>
80 C: <=
25 H: <=
200 I: <=
Where I'm having trouble is working with the output. The result I'd like to achieve is an output stating "Disk n is smaller than required!". I know that everything with the side indicator "<=" is the required value and everything with the "=>" side indicator is the given value. I've tried a foreach statement but I am unable to process the data as needed - I need to check the given value against the required value and if it's smaller, tell me so. How can I again compare these values as required? Basically a "foreach object where SideIndicator is <= compare to object where SideIndicator is => and DeviceID equals DeviceID". How do I translate that into proper code?
It looks to me like the Compare-Object is doing a double comparison on both properties. The documentation or another StackOverflow soul may be able to help with that command.
My approach would be to translate your pseudo-code into code:
foreach ($disk in $SystemDisks){
$ref = $RequiredDisks | Where-object {$_.DeviceID -eq $disk.DeviceID}
if([int]($disk.SizeGB) -lt [int]($ref.SizeGB){
Write-Output "Disk $($disk.DeviceID) is smaller than required!"
}
}
I guess the question is in the title.
I have a CSV that looks something like
user,path,original_path
I'm trying to find duplicates on the original path, then output both the user and original_path line.
This is what I have so far.
$2 = Import-Csv 'Total 20_01_16.csv' | Group-Object -Property Original_path |
Where-Object { $_.count -ge 2 } | fl Group | out-string -width 500
This gives me the duplicates in Original_Path. I can see all the required information but I'll be danged if I know how to get to it or format it into something useful.
I did a bit of Googleing and found this script:
$ROWS = Import-CSV -Path 'Total 20_01_16.csv'
$NAMES = #{}
$OUTPUT = foreach ( $ROW in $ROWS ) {
IF ( $NAMES.ContainsKey( $ROW.Original_path ) -and $NAMES[$ROW.original_path] -lt 2 )
{ $ROW }
$NAMES[$ROW.original_path] += 1 }
Write-Output $OUTPUT
I'm reluctant to use this because, well first I have no idea what it's doing. So little of the makes any sense to me, I don't like using scripts I can't get my head around.
Also, and this is the more important part, it's only giving me a single duplicate, it's not giving me both sets. I'm after both offending lines, so I can find both users with the same file.
If anyone could be so kind as to lend a hand I'd appreciate it.
Thanks
It depends on the output format you need, but to build on what you already have we can use this to show the records in the console:
Import-Csv 'Total 20_01_16.csv' |
Group-Object -Property Original_path |
Where-Object { $_.count -ge 2 } |
Foreach-Object { $_.Group } |
Format-Table User, Path, Original_path -AutoSize
Alternatively, use this to save them in a new csv-file:
Import-Csv 'Total 20_01_16.csv' |
Group-Object -Property Original_path |
Where-Object { $_.count -ge 2 } |
Foreach-Object { $_.Group } |
Select User, Path, Original_path |
Export-csv -Path output.csv -NoTypeInformation