Powershell Sort-Object Name with numbers doesn't properly

前端 未结 4 1469
眼角桃花
眼角桃花 2021-01-06 04:23

I am trying to find .sql files in a folder and filtering them based on the last write time. Based on the last write time I got 4 files as output.

TestScript1         


        
相关标签:
4条回答
  • 2021-01-06 05:02

    Thanks for all your suggestions above for my question. After streamlining the suggestions, the code below worked well for my situation. This is helping me sort in the natural order like Windows Explorer does.

    $ToNatural= { [regex]::Replace($_, '\d+',{$args[0].Value.Padleft(20)})}
    $File= Get-ChildItem $FileLocation -Filter *.sql | Where-Object {$_.LastWriteTime -gt $datetime} | Sort-Object $ToNatural
    
    0 讨论(0)
  • 2021-01-06 05:13

    Hm... finally figure it out.

    Windows explorer is using a legacy API in shlwapi.dll called StrCmpLogicalW when sorting strings.

    I don't want to use padding zeros, so wrote a script.

    https://github.com/LarrysGIT/Powershell-Natural-sort

    Find the following powershell script, it using the same API. You may need to check the latest code from the repo as I am not updating here always.

    function Sort-Naturally
    {
        PARAM(
            [System.Collections.ArrayList]$Array,
            [switch]$Descending
        )
    
        Add-Type -TypeDefinition @'
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Runtime.InteropServices;
    namespace NaturalSort {
        public static class NaturalSort
        {
            [DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
            public static extern int StrCmpLogicalW(string psz1, string psz2);
            public static System.Collections.ArrayList Sort(System.Collections.ArrayList foo)
            {
                foo.Sort(new NaturalStringComparer());
                return foo;
            }
        }
        public class NaturalStringComparer : IComparer
        {
            public int Compare(object x, object y)
            {
                return NaturalSort.StrCmpLogicalW(x.ToString(), y.ToString());
            }
        }
    }
    '@
        $Array.Sort((New-Object NaturalSort.NaturalStringComparer))
        if($Descending)
        {
            $Array.Reverse()
        }
        return $Array
    }
    

    Find the test results below.

    PS> # Natural sort
    PS> . .\NaturalSort.ps1
    PS> Sort-Naturally -Array @('2', '1', '11')
    1
    2
    11
    PS> # If regular sort is used
    PS> @('2', '1', '11') | Sort-Object
    1
    11
    2
    

    And,

    PS> # Not good
    PS> $t = (ls .\Scripts*.txt).name
    PS> $t | Sort-Object
    Scripts1.txt
    Scripts10.txt
    Scripts2.txt
    PS> # Good
    PS> Sort-Naturally -Array $t
    Scripts1.txt
    Scripts2.txt
    Scripts10.txt
    
    0 讨论(0)
  • 2021-01-06 05:17

    I like @mjolinor solution better, as it shows how powerful sorting in PowerShell can be. But just in case you would like to "fix" file names with prefix mentioned in comments:

    Get-ChildItem Test*.sql | 
        Rename-Item -NewName { 'TestScript{0:D2}.sql' -f [int]($_.BaseName -replace '\D') }
    

    Once renamed, files will be sorted as you expected. If you need more than two digits - just change formating ({0:D#}).

    0 讨论(0)
  • 2021-01-06 05:18

    Something like this:

    | sort-object {[int]($_.basename -replace '\D')}
    
    0 讨论(0)
提交回复
热议问题