Select-Objectでプロパティを指定してから表示
# PowerShell 5.1, Windows 11 (2024年2月頃) Set-StrictMode -Version Latest Add-Type -Language CSharp -Namespace Win32API -Name Shlwapi -MemberDefinition @' [DllImport("Shlwapi.dll", EntryPoint = "StrCmpLogicalW", CharSet = CharSet.Unicode)] public static extern int StrCmpLogicalW([MarshalAs(UnmanagedType.LPWStr)] string psz1, [MarshalAs(UnmanagedType.LPWStr)] string psz2); '@ # 配列 $psObjs = [PSObject[]]@( [PSCustomObject]@{ Name="05 file.txt" ; A="ValA" } [PSCustomObject]@{ Name="050 file.txt"; B="ValB" } [PSCustomObject]@{ Name="1 file.txt" ; C="ValC" } [PSCustomObject]@{ Name="10 file.txt" ; D="ValD" } [PSCustomObject]@{ Name="100 file.txt" } ) # 配列をソート [System.Array]::Sort($psObjs, { [Win32API.Shlwapi]::StrCmpLogicalW($args[0].Name, $args[1].Name) } -as [System.Comparison[PSObject]] ) # プロパティ名 $propNames = $psObjs.ForEach({ $_.PSObject.Properties.ForEach({ $_.Name }) }) | Sort-Object | Get-Unique $propNames = @("Name") + @($propNames -ne "Name") # 表示 $psObjs | ConvertTo-Csv -NoTypeInformation | ConvertFrom-Csv | Format-Table -AutoSize | Out-String | Write-Host # Name C # ---- - # 1 file.txt ValC # 05 file.txt # 10 file.txt # 050 file.txt # 100 file.txt # Select-Objectでプロパティを指定してから表示 $psObjs | Select-Object -Property $propNames | ConvertTo-Csv -NoTypeInformation | ConvertFrom-Csv | Format-Table -AutoSize | Out-String | Write-Host # Name A B C D # ---- - - - - # 1 file.txt ValC # 05 file.txt ValA # 10 file.txt ValD # 050 file.txt ValB # 100 file.txt
# PowerShell 5.1, Windows 11 (2024年2月頃) Set-StrictMode -Version Latest Add-Type -Language CSharp -Namespace Win32Functions -Name Shlwapi -MemberDefinition @' [DllImport("Shlwapi.dll", EntryPoint = "StrCmpLogicalW", CharSet = CharSet.Unicode)] public static extern int StrCmpLogicalW([MarshalAs(UnmanagedType.LPWStr)] string psz1, [MarshalAs(UnmanagedType.LPWStr)] string psz2); '@ # 並べ替え後のFileSystemInfoの配列を取得 $fsis = & { param ([HashTable]$Splatting) # Get-ChildItemにてFileInfoとDirectoryInfoを取得 $fsis = Get-ChildItem @Splatting # AddRangeを使うため $fsiList = [System.Collections.Generic.List[System.IO.FileSystemInfo]]::new() # Comparison $cmpName = { param ($x, $y); return [Win32Functions.Shlwapi]::StrCmpLogicalW($x.Name, $y.Name) } $comparisonGroupInfo = [System.Comparison[Microsoft.PowerShell.Commands.GroupInfo]]$cmpName $comparisonDirectoryInfo = [System.Comparison[System.IO.DirectoryInfo]]$cmpName $comparisonFileInfo = [System.Comparison[System.IO.FileInfo]]$cmpName # Group-ObjectにてPSParentPathでグループ化 $grs = [Microsoft.PowerShell.Commands.GroupInfo[]]@($fsis | Group-Object -Property PSParentPath) # GroupInfoの配列をArray.Sortで並べ替え [System.Array]::Sort($grs, $comparisonGroupInfo) for ($i = 0; $i -lt $grs.Length; $i++) { $fsisGr = [System.IO.FileSystemInfo[]]@($grs[$i].Group) # フォルダ $disGr = [System.IO.DirectoryInfo[]]@($fsisGr.Where({ [System.IO.Directory]::Exists($_.FullName) })) [System.Array]::Sort($disGr, $comparisonDirectoryInfo) $fsiList.AddRange($disGr) # ファイル $fisGr = [System.IO.FileInfo[]]@($fsisGr.Where({ [System.IO.File]::Exists($_.FullName) })) [System.Array]::Sort($fisGr, $comparisonFileInfo) $fsiList.AddRange($fisGr) } if ($fsiList.Count -ne $fsis.Length) { throw } return (, [System.IO.FileSystemInfo[]]$fsiList) } -Splatting @{ LiteralPath="$env:USERPROFILE"; Force=$true; Recurse=$true; Depth=3 } # 並べ替え後のプロパティ名を取得 $propertyNames = & { param ([PSObject[]]$PSObjects) # UnionWithを使うため $propNameSet = [System.Collections.Generic.HashSet[string]]::new() # 各要素のプロパティ名をHashSetに追加 ($PSObjects -ne $null).ForEach({ $propNameSet.UnionWith([string[]]$_.PSObject.Properties.ForEach({ $_.Name })) }) # 配列に変換 $propNames = [string[]]$propNameSet # 配列の並べ替え $cmp = [System.Comparison[string]]{ param ($x, $y); return [Win32Functions.Shlwapi]::StrCmpLogicalW($x, $y) } [System.Array]::Sort($propNames, $cmp) return (, $propNames) } -PSObjects $fsis # スプラッティング $splatting = Invoke-Command -NoNewScope -ScriptBlock $([ScriptBlock]::Create(@' @{ Property = @( @{ Name="_ParentPath"; Expr={ Convert-Path -LiteralPath $_.PSParentPath } }, @{ Name="_Name" ; Expr={ $_.Name } } ) + $propertyNames ExcludeProperty = @("Target", "VersionInfo") } '@)) $fsis | Select-Object @splatting | ConvertTo-Csv -NoTypeInformation | Set-Clipboard