Powershell Sort-Object Name with numbers doesn't properly

前端 未结 4 1497
眼角桃花
眼角桃花 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条回答
  •  梦毁少年i
    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
    

提交回复
热议问题