How to sort unique most recent file with Powershell - powershell

In my folder testtemp, I've got this files
PS C:\scripts\testtemp> Get-ChildItem | select name,lastwritetime
Name LastWriteTime
---- -------------
AABASSI.TMC049913.mapdrives.txt 27/02/2015 11:01:11
AABASSI.TMC049916.mapdrives.txt 02/03/2015 14:29:31
AABASSI.TMC050020.mapdrives.txt 26/11/2014 18:08:48
aabassi.TMS064845.mapdrives.txt 06/03/2015 14:14:50
aaboud.DLECLERCQPC.mapdrives.txt 03/04/2015 09:02:03
aaboud.FHP030221.mapdrives.txt 30/12/2014 15:05:04
aaboud.FHP045846.mapdrives.txt 18/11/2014 10:15:05
Aaccus.FHP047416.mapdrives.txt 25/07/2014 08:16:19
AADRIENVASSE.PHP049659.mapdrives.txt 02/10/2015 14:18:15
AADRIENVASSE.RBXXAMET10.mapdrives.txt 06/08/2015 10:33:33
aagostini.FHP047082.mapdrives.txt 05/03/2015 13:38:07
aagricole.PHP053341.mapdrives.txt 30/03/2015 15:09:03
aagricole.TMS064745.mapdrives.txt 25/03/2015 12:32:06
aaiad.PHP053346.mapdrives.txt 09/06/2015 09:18:58
aaissaoui.FHP029908.mapdrives.txt 28/08/2014 14:41:09
aaissaoui.FHP030685.mapdrives.txt 15/11/2014 18:27:55
aaissaoui.FHP048791.mapdrives.txt 12/09/2014 10:22:19
aaissaoui.FHP048963.mapdrives.txt 06/11/2014 09:55:00
I just want to get only the most recent file for each login (for exemple AABASSi is a login)
If I try sort-object lastwritetime -descending and sort-object -property name -unique, there is a problem because for exemple, AAISSAOUI 28/08/2014 14:41:09 is NOT the most recent file :
Get-ChildItem | select #{l="name";e={($_.name.split(".")[0]).ToUpper()}},lastwritetime | Sort-Object lastwritetime -Descending | Sort-Object -Property name -Unique
name LastWriteTime
---- -------------
AABASSI 26/11/2014 18:08:48
AABOUD 30/12/2014 15:05:04
AACCUS 25/07/2014 08:16:19
AADRIENVASSE 02/10/2015 14:18:15
AAGOSTINI 05/03/2015 13:38:07
AAGRICOLE 25/03/2015 12:32:06
AAIAD 09/06/2015 09:18:58
AAISSAOUI 28/08/2014 14:41:09
Is ther a simple solution for my problem ?

The reason you're having the issue with sorting is that you sort it by the property you actually want, and then you sort it again by a different property (Name). Instead, group the objects by the string before the ".", and select only the newest object from each group. #PetSerAl's method is great:
Get-ChildItem | Group-Object {$_.Name.Split(".")[0]} | % {
$_.Group | Sort-Object LastWriteTime -Descending | Select-Object -First 1
}

Related

Powershell: How To Extract Binary File Attributes From Directory Listing

In PowerShell, I can get a nice list of files in descending sorted order using a filter:
$tt = gci -Path \\Munis2\musys_read\export_test\* -Include "ARLMA_*.csv" | sort LastWriteTime -Descending
PS H:\WindowsPowerShell\Scripts\ProductionScripts\Munis> $tt
Directory: \\Munis2\musys_read\export_test
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 03/04/2022 3:09 AM 25545520 ARLMA_20220304030027.csv
.
.
.
Then, I can get just the name of the file for the purposes of transferring that file to an FTP site.
PS H:\WindowsPowerShell\Scripts\ProductionScripts\Munis> $tt[0].Name
ARLMA_20220304030027.csv
How can I parse $tt[0].LastWriteTime
PS H:\WindowsPowerShell\Scripts\ProductionScripts\Munis> $tt[0].LastWriteTime
Friday, March 4, 2022 3:09:14 AM
into something that looks like yymmddhhmmss, or is there a way to get the binary time of the file the last time it was accessed?
The ToString() method can be used to format the date into a string. Are you sure that a two digit year is appropriate?
$DateResult = (Get-ChildItem -Path \\Munis2\musys_read\export_test\* -Include "ARLMA_*.csv" |
Sort-Object -Property LastWriteTime -Descending |
Select-Object -First 1).LastWriteTime.ToString('yyMMddHHmmss')

Get all directories in directory that has a numeric name with powershell

I will start off by saying I am new to powershell...
I can get all the directories in a specified directory but I need to only get the directories that their names are numeric. Example:
1 - include
2 - include
3 - include
10 - include
LastFailed - exclude
I also will need to order them in sequential order for later processing.
Here is what I have so far:
$Dirs = Get-ChildItem -Path ..\..\..\builds -Attributes D
foreach($D in $Dirs)
{
Write-Host $D.Name
}
To get a list of just the folders that have numeric names, you can do this:
$Path = '..\..\..\builds'
$Dirs = Get-ChildItem -Path $Path -Attributes D |
Where-Object { $_.Name -match '^\d+$' } |
Sort-Object
$Dirs
This code above uses the Where-Object clause to filter out only the folders that have a numeric-only name.
It does this by using the -match operator and the regular expression ^\d+$ where:
`^` --> start at the beginning of the line
`\d` --> look for numeric values (0-9)
`+` --> there must be 1 or more numeric values present
`$` --> the end of the string
Instead of \d it could also have been written using [0-9]
The code ends with Sort-Object because the OP wants the list of folders sorted.
because we do not tell what property to sort on here, Powershell defaults to the Name.
The above will produce a list like:
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 18-8-2018 16:13 1
d----- 18-8-2018 16:13 10
d----- 18-8-2018 16:13 2
d----- 18-8-2018 16:13 5
As you can see, the list is sorted by property Name, but.. the numbers were treated as strings, so '10' follows '1'.
What we most likely want to do here is to have the Sort-Object treat the names as real Numbers, not strings.
To fix that we add the Select-Object cmdlet in order to create our own objects with properties we need.
We can get standard properties of the DirInfo object that is coming through the pipeline, AND it is possible to create a new calculated property.
Here I add the calculated property called SortIndex that is simply the numeric value converted from the Name, which we will then use for the numeric sort:
$Dirs = Get-ChildItem -Path $Path -Attributes D |
Where-Object { $_.Name -match '^\d+$' } |
Select-Object -Property FullName, Name, LastWriteTime, #{Name = 'SortIndex'; Expression = {[int]$_.Name} } |
Sort-Object -Property SortIndex
$Dirs
Now it produces an array of objects that when printed to console looks like this:
FullName Name LastWriteTime SortIndex
-------- ---- ------------- ---------
D:\Temp\1 1 18-8-2018 16:13:22 1
D:\Temp\2 2 18-8-2018 16:13:25 2
D:\Temp\5 5 18-8-2018 16:13:28 5
D:\Temp\10 10 18-8-2018 16:13:31 10
Hope this helps.
You can utilize Where-Object to filter your collection:
$dirs = Get-ChildItem -Path ..\..\..\builds -Directory |
Where-Object -Property Name -Match '\d'
This operation uses regex to match the digit class.
If you meant you only want the directory names that start with a digit, you can use an anchor:
'^\d'
and lastly, you can sort them with Sort-Object:
$dirs = Get-ChildItem -Path ..\..\..\builds -Directory |
Where-Object -Property Name -Match '^\d' |
Sort-Object -Property Name
You can further enhance this sort by being explicit about the starting digit:
-Property {[int]($_.Name -split '[^\d]')[0]}
In this context, we're splitting on the first non-digit character and capturing the first fragment that was split off (which should be the number represented as a string, so we cast to an integer).

How to get a numbered count of different items in powershell

Im using the following powershell query to get a list of disks:
Get-NcDisk | Select-Object -Property model | Sort-Object -Property Model -Descending | foreach {$_.model}
It outputs like below:
X316_SMKRE06TA07
X316_HARIH06TA07
X316_HARIH06TA07
X316_HARIH06TA07
How can I get it to output a numbered count of each type of disk like below:
1 X316_SMKRE06TA07
3 X316_HARIH06TA07
Group-Object will do this for you..
I can't use Get-NcDisk but it may just be:
Get-NcDisk | Select-Object -ExpandProperty model | Group-Object
Example output using a string array:
"X316_SMKRE06TA07","X316_HARIH06TA07","X316_HARIH06TA07","X316_HARIH06TA07" | Group-Object
Count Name Group
----- ---- -----
1 X316_SMKRE06TA07 {X316_SMKRE06TA07}
3 X316_HARIH06TA07 {X316_HARIH06TA07, X316_HARIH06TA07, X316_HARIH06TA07}

Trying to display the contents of a folder including the size, date modified, and length

This script is working so far, but I need the size to be in KB. It works as well, but when I call for a list of files it just outputs the KB size below the list, instead of within the list of itself.
$fileList = Get-ChildItem "E:\"
foreach($file in $fileList) {
ls $file | select -Property fullName, LastWriteTime, length
}
foreach($file in $fileList) {
Write-Host((Get-Item $file).length/1KB) | Sort-Object fullName, LastWriteTime, length
}
I want to see how I can get the KB size to populate the list under length, instead of the default file size being displayed.
You can Select-Object to get only the properties you want:
Get-ChildItem "E:\" | Select-Object fullName,LastWriteTime,Length
FullName LastWriteTime Length
-------- ------------- ------
C:\folder\cluster_totals.xlsx 14/12/2017 15:11:40 9382
C:\folder\IAG.xlsx 23/11/2017 11:05:12 13054
C:\folder\Offline.xml 30/10/2017 16:14:24 21503
And then use Calculated Properties to change the formatting of the Length property into KB.
Get-ChildItem "E:\" | Select-Object fullName,LastWriteTime,#{Name="KB";Expression={"{0:N0}" -f ($_.Length / 1KB)}}
Which will give you something like this:
FullName LastWriteTime KBytes
-------- ------------- ------
C:\folder\cluster_totals.xlsx 14/12/2017 15:11:40 9
C:\folder\IAG.xlsx 23/11/2017 11:05:12 13
C:\folder\Offline.xml 30/10/2017 16:14:24 21

Sort-Object by greatest numerical value value from Import-CSV

I want the greatest value (mailboxSize) at the top of the file. I have a cvs as inport.
When I do the following sort cmd:
Import-Csv import.csv| Sort-Object MailboxSize,DisplayName -Descending | Export-Csv SORT.csv
I get the following result:
"DisplayName","MailboxSize"
"persone6","9941"
"persone3","8484"
"persone1","7008"
"persone4","4322"
"persone5","3106"
"persone7","27536"
"persone10","24253"
"persone8","1961"
"persone9","17076"
"persone11","17012"
"persone2","15351"
"persone12","11795"
"persone14","1156"
"persone13","1008"
But I want this as a result!
"persone7","27536"
"persone10","24253"
"persone9","17076"
"persone11","17012"
"persone2","15351"
"persone12","11795"
"persone6","9941"
"persone3","8484"
"persone1","7008"
"persone4","4322"
"persone5","3106"
"persone14","1156"
"persone13","1008"
When importing a CSV-file, all properties are made string-type. You have to cast the MailboxSize to an int before you can sort it properly. Try:
Import-Csv import.csv |
Sort-Object {[int]$_.MailboxSize}, DisplayName -Descending |
Export-Csv SORT.csv
You should also use the -NoTypeInformation switch in Export-CSV to avoid the #TYPE ..... line (first line in an exported CSV-file).
Sample:
$data = #"
"DisplayName","MailboxSize"
"persone6","9941"
"persone3","8484"
"persone1","7008"
"persone4","4322"
"persone5","3106"
"persone7","27536"
"persone10","24253"
"persone8","1961"
"persone9","17076"
"persone11","17012"
"persone2","15351"
"persone12","11795"
"persone14","1156"
"persone13","1008"
"# | ConvertFrom-Csv
$data |
Sort-Object {[int]$_.MailboxSize}, DisplayName -Descending |
Export-Csv SORT.csv -NoTypeInformation
SORT.csv
"DisplayName","MailboxSize"
"persone7","27536"
"persone10","24253"
"persone9","17076"
"persone11","17012"
"persone2","15351"
"persone12","11795"
"persone6","9941"
"persone3","8484"
"persone1","7008"
"persone4","4322"
"persone5","3106"
"persone8","1961"
"persone14","1156"
"persone13","1008"
I'm guessing the usernames are fake, but be aware that the same issue goes for DisplayName if your usernames actually was personeXX where XX is an int. Like:
persone7 27536
persone20 27536
persone13 27536
To sort them probably, you'd have to create a scriptblock for Sort-Object or create your own function to split the value and sort them correctly.