I have files like this in folder:
C:\G1001
C:\G1002
C:\G2001
C:\G2002
C:\G2003
C:\1G001
C:\1G003
C:\1G025
How do I get the latest file based on 1st 2 chars of file name.
I need output like this (using powershell):
C:\G1002
C:\G2003
C:\1G025
You can combine Group-Object with Sort-Object:
Group the files by the first 2 chars of it's BaseName - Group-Object { -join $_.BaseName[0..1] }
Count Name Group
----- ---- -----
3 1G {/path/to/folder/1G001.ext, /path/to/folder....
2 G1 {/path/to/folder/G1001.ext, /path/to/folder....
3 G2 {/path/to/folder/G2001.ext, /path/to/folder....
For each group, sort them -Descending (from highest to lowest) and get the first one with Select-Object -First 1
Get-ChildItem path/to/files | Group-Object { -join $_.BaseName[0..1] } |
ForEach-Object {
$_.Group | Sort-Object BaseName -Descending | Select-Object -First 1
}
Example
[System.IO.FileInfo[]]$files = #'
G1001.ext
G1002.ext
G2001.ext
G2002.ext
G2003.ext
1G001.ext
1G003.ext
1G025.ext
'# -split '\r?\n'
$files | Group-Object { -join $_.BaseName[0..1] } |
ForEach-Object {
$_.Group | Sort-Object BaseName -Descending |
Select-Object FullName, Name -First 1
}
# Results in:
FullName Name
-------- ----
/path/to/folder/1G025.ext 1G025.ext
/path/to/folder/G1002.ext G1002.ext
/path/to/folder/G2003.ext G2003.ext
Related
This is based on another question: https://stackoverflow.com/a/9675811/14529561.
How would I pass the result from gci path | sort LastWriteTime | select -last 1 and open with explorer.exe?
I have tried:
$wd = gci path | sort LastWriteTime | select -last 1;
explorer $wd
gci path | sort LastWriteTime | select -last 1 | Format-Table -hidetableheaders | explorer $_.
gci path | sort LastWriteTime | select -last 1 | Format-Table -hidetableheaders | ii $_.
Unfortunately, all the above give me give me errors.
You can reference the PSParentPath property.
Get-ChildItem -Path path |
Sort-Object -Property LastWriteTime |
Select-Object -Last 1 | Foreach-Object {
Invoke-Item $_.psparentpath
}
You can do it like this :
$Mypath=$Env:Temp
gci $Mypath | sort LastWriteTime | select -last 1 | % { Explorer /n,/select,$_.FullName }
And if you want to explore in more than folder, you can put thel into an array and do like this :
cls
$Mypath=#("$Env:UserProfile\desktop","$Env:Temp","$Env:AppData")
ForEach ($P in $Mypath) {
gci $P | sort LastWriteTime | select -last 1 | % { Explorer /n,/select,$_.FullName }
}
This my code so far:
# Master
Import-Csv -Path "C:\PS\SessionData\MasterList.csv" | Select-Object "Service Unit",#{ Name='UserID';Expression = { $PSItem.'UserID'.ToLower()} } | Export-Csv C:\PS\SessionData\MasterList2Col.csv -NoTypeInformation
# Get list of total numbers per Service Unit
Import-Csv -Path "C:\PS\SessionData\MasterList2Col.csv" | Select-Object -ExpandProperty "Service Unit" | Group-Object | Select-Object Name,Count | Out-File "C:\PS\SessionData\countUsersByBU.txt"
#Citrix
Import-Csv -Path "C:\PS\SessionData\Session Summary 09_04_2020.csv" | Select-Object -Property #{ Name="UserID";Expression={ $PSItem."Associated User" } } -Unique | Export-Csv -Path "C:\PS\SessionData\sessionCRX.csv" -NoTypeInformation
$citrixUsers = Import-Csv -Path "C:\PS\SessionData\sessionCRX.csv" | Select-Object -ExpandProperty UserID
Import-Csv -Path "C:\PS\SessionData\MasterList2Col.csv" | Where-Object {$citrixUsers -contains $PSItem.UserID} | ForEach-Object {"$($PsItem.'Service Unit')" } | Out-File "C:\PS\SessionData\totalCRX.txt"
$fileCRX = "C:\PS\SessionData\totalCRX.txt"
Get-Content $fileCRX | Group-Object | Select-Object Name,Count | Out-File C:\PS\SessionData\countCRX.txt
#VPN
Import-Csv -Path "C:\PS\SessionData\Cisco Anyconnect users 09-04.csv" | Where-Object { $PSItem.Status -eq 'Active' } | Select-Object #{Name = 'UserID'; Expression = {($_.Name -split '\\',2)[-1] }} -Unique | Export-Csv -Path "C:\PS\SessionData\sessionVPN.csv" -NoTypeInformation
$vpnUsers = Import-Csv -Path "C:\PS\SessionData\sessionVPN.csv" | Select-Object -ExpandProperty UserID
Import-Csv -Path "C:\PS\SessionData\MasterList2Col.csv" | Where-Object {$vpnUsers -contains $PSItem.UserID} | ForEach-Object {"$($PsItem.'Service Unit')" } | Out-File "C:\PS\SessionData\totalVPN.txt"
$fileVPN = "C:\PS\SessionData\totalVPN.txt"
Get-Content $fileVPN | Group-Object | Select-Object Name,Count | Out-File C:\PS\SessionData\countVPN.txt
#Create new csv file with totals
$txtMain = "C:\PS\SessionData\countUsersByBU.txt"
$txtCRX = "C:\PS\SessionData\countCRX.txt"
$txtVPN = "C:\PS\SessionData\countVPN.txt"
#End result new.csv
#Get-Content ??? | Export-Csv -Path "C:\PS\SessionData\new.csv"
I have three text files, which has a "Name" column and a "Count" column, example below:
$txtMain = "C:\PS\SessionData\countUsersByBU.txt"
Name Count
---- -----
HR 20
Account 25
Dev 25
Sales 25
Garden 10
$txtCRX = "C:\PS\SessionData\countCRX.txt"
Name Count
---- -----
HR 3
Account 6
Dev 9
Garden 7
$txtVPN = "C:\PS\SessionData\countVPN.txt"
Name Count
---- -----
HR 7
Account 8
Dev 1
Sales 5
I need to get this data into a new.csv file. Where the txtMain data has all Name columns and a total count column.
The data from txtOne, needs to check the new.csv file for the Name column and put the Count value into a third column.
The data from txtTwo, needs to check the new.csv file for the Name column and put the Count value into a fourth column.
e.g. new.csv
Name (txtMain) (txtCRX) (txtVPN) (Percentage)
---- --------- -------- -------- ------------
HR 20 3 7 50%
Account 25 7 8 60%
Dev 25 9 1 40%
Sales 25 5 20%
Garden 10 7 70%
Then a final column which is a calculated expression, which calculates the percentage of txtCRX and txtVPN columns from the txtMain column.
Apologies for the noob question, haven't worked with Powershell for a while and not sure how to write the final Get and Export statement to create the new.csv file.
Using your example input files, You can do this:
# Create an object collection with totals counts from the helper files
$result = Import-Csv -Path "C:\PS\SessionData\countUsersByBU.txt" | Select-Object *,countCRX,countVPN
# add info from countCRX.txt
Import-Csv -Path "C:\PS\SessionData\countCRX.txt" | ForEach-Object {
$name = $_.Name
$item = $result | Where-Object { $_.Name -eq $name }
if ($item) { $item.CountCRX = [int]$_.Count }
}
# add info from countVPN.txt
Import-Csv -Path "C:\PS\SessionData\countVPN.txt" | ForEach-Object {
$name = $_.Name
$item = $result | Where-Object { $_.Name -eq $name }
if ($item) { $item.CountVPN = [int]$_.Count }
}
# finally calculate the percentages
$result = $result | Select-Object *, #{Name = 'Percentage'; Expression = {'{0:P0}' -f (([int]$_.countCRX + [int]$_.countVPN) / [int]$_.Count)}}
# output on screen
$result | Format-Table -AutoSize
# output to CSV
$result | Export-Csv -Path 'C:\PS\SessionData\new.csv' -UseCulture -NoTypeInformation
Output on screen:
Name Count countCRX countVPN Percentage
---- ----- -------- -------- ----------
HR 20 3 7 50%
Account 25 6 8 56%
Dev 25 9 1 40%
Sales 25 5 20%
Garden 10 7 70%
P.S. you should create the 3 files countUsersByBU.txt, countCRX.txt and CountVPN.txt with
Export-Csv -Path 'X:\thefile -NoTypeInformation instead of Out-File to get usable files to work with.
Normally you would give them the .csv extension, but.txt will also work (although technically incorrect..)
I am trying to combine several rows into one, provided that the key cell is the same. And write data from all lines with the same key to the final line.
Example Pic
**Before**
ID | Name | DateTime | Duration | Call_Type |
1234509 | Mike | 2020-01-02T01:22:33 | | Start_Call |
1234509 | | 2020-01-02T01:32:33 | 600 | End_call |
AFTER
ID | Name | DateTime | Duration | Start_Call | End_call |
1234509 | Mike | 2020-01-02T01:22:33 | 600 |2020-01-02T01:22:33 | 2020-01-02T01:32:33 |
Before
ID;Name;DateTime;Duration;Call_Type
1234509;Mike;2020-01-02T01:22:33;;Start_Call
1234509;;2020-01-02T01:32:33;600;End_call
After
ID;Name;Duration;Start_Call;End_call
1234509;Mike;600;2020-01-02T01:22:33;2020-01-02T01:32:33
How to use here
$csv | Group-Object ID
and get the data as in the picture?
After grouping by ID with Group-Object, you can iterate each group and create a new System.Management.Automation.PSCustomObject with the properties you want to export in your output CSV file.
For ID we simply use the grouping key. Name and Duration we choose the first object that doesn't have a $null or empty version of that property using System.String.IsNullOrEmpty(). For Start_Call and End_Call we choose the object that has those values for the Call_Type property.
The filtering is done by Where-Object. To get the first and expanded versions of the properties, we also use -First and -ExpandProperty from Select-Object.
$csv = Import-Csv -Path .\data.csv -Delimiter ";"
$groups = $csv | Group-Object -Property ID
& {
foreach ($group in $groups)
{
[PSCustomObject]#{
ID = $group.Name
Name = $group.Group | Where-Object {-not [string]::IsNullOrEmpty($_.Name)} | Select-Object -First 1 -ExpandProperty Name
Duration = $group.Group | Where-Object {-not [string]::IsNullOrEmpty($_.Duration)} | Select-Object -First 1 -ExpandProperty Duration
Start_Call = $group.Group | Where-Object {$_.Call_Type -eq "Start_Call"} | Select-Object -First 1 -ExpandProperty DateTime
End_Call = $group.Group | Where-Object {$_.Call_Type -eq "End_Call"} | Select-Object -First 1 -ExpandProperty DateTime
}
}
} | Export-Csv -Path .\output.csv -Delimiter ";" -NoTypeInformation
output.csv
"ID";"Name";"Duration";"Start_Call";"End_Call"
"1234509";"Mike";"600";"2020-01-02T01:22:33";"2020-01-02T01:32:33"
If you want to remove quotes from the CSV file, you can use the -UseQuotes switch from Export-Csv. However, yhis does require PowerShell 7. If your using a lower PowerShell version, you can use some of the recommendations from How to remove all quotations mark in the csv file using powershell script?.
Using Powershell I created a data set like this.
Count Name Group
----- ---- -----
2 108005 {108005, 108005}
2 114763 {114763, 114763}
2 115826 {115826, 115826}
2 115925 {115925, 115925}
2 117435 {117435, 117435}
2 114152 {114152, 114152}
2 117093 {117093, 117093}
Using this code.
$check = Get-Content $file | Group | Where {$_.count -gt 1}
I used the code to check for duplicates and cannot figure out how to output the Name column to a list in a plain txt file with only the names. There doesn't seem to be much documentation on how to do this. Is this even possible?
Use either ForEach-Object or Select-Object -ExpandProperty:
$duplicates = Get-Content $file | Group | Where {$_.count -gt 1} |Select-Object -ExpandProperty Name
Since you don't need anything other than the name, you can avoid generating the individual sets during grouping, with the -NoElement switch parameter:
$duplicates = Get-Content $file | Group -NoElement | Where {$_.count -gt 1} |Select-Object -ExpandProperty Name
Right now, I have the following code:
import-csv $import | ? {$_.'Summary' -like '*apple*'} | Group-Object {$_.'Value1'} | Sort-Object -Property Name| Format-Table Count,Name -AutoSize|Out-File $export
import-csv $import | ? {$_.'Summary' -like '*orange*'} | Group-Object {$_.'Value1'} | Sort-Object -Property Name| Format-Table Count,Name -AutoSize|Out-File $export -append
import-csv $import | ? {$_.'Summary' -like '*banana*'} | Group-Object {$_.'Value1'} | Sort-Object -Property Name| Format-Table Count,Name -AutoSize|Out-File $export -append
My output looks something like this:
Count Name
----- ----
4 Juice
2 Pie
6 Tart
Count Name
----- ----
36 Juice
1 Pie
Count Name
----- ----
46 Tart
I want to take the values output as the Count from my table, and add them together in a variable. How would I go about doing this?
Use the Measure-Object on the content of the files and store in a variable
$a = (Get-Content $import | Measure-Object -line )
EDIT
$a = 0
import-csv $import | ? {$_.'Summary' -like '*apple*'} | Group-Object {$_.'Value1'} | Sort-Object -Property Name| Foreach {$a += $_.Count} | Format-Table Count,Name -AutoSize|Out-File $export