Powershell带数字的排序对象名称不正确

use*_*372 4 .net powershell

我试图在文件夹中查找.sql文件,并根据上次写入时间对其进行过滤。根据上次写入时间,我得到了4个文件作为输出。

TestScript10.sql TestScript5.sql TestScript6.sql TestScript7.sql

现在,当我的命令尝试执行排序对象时,我在顶部看到了Testscript10而不是TestScript5,如何解决此问题?

我的代码”

$File= Get-ChildItem $FileLocation -Filter *.sql | Where-Object {$_.LastWriteTime -gt $datetime} | Sort-Object Name
Run Code Online (Sandbox Code Playgroud)

$文件输出

[DBG]:PS SQLSERVER:>> $ File

Directory: C:\SQLScripts
Run Code Online (Sandbox Code Playgroud)

模式LastWriteTime长度名字
---- ------------- ------ ----
-a --- 2014年5月22日上午10:20 61 TestScript10.sql
- a --- 2014年5月22日10:16 AM TestScript5.sql
-a --- 2014年5月22日10:24 AM 66 TestScript6.sql
-a-2014年5月22日10:10 24 Testscript7.sql

Lar*_*ong 6

嗯……终于想通了。

Windows 资源管理器在对字符串进行排序时使用 shlwapi.dll 中名为 StrCmpLogicalW 的旧 API。

我不想使用填充零,所以写了一个脚本。

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

找到以下 powershell 脚本,它使用相同的 API。您可能需要检查 repo 中的最新代码,因为我并不总是在这里更新。

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
}
Run Code Online (Sandbox Code Playgroud)

在下面找到测试结果。

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
Run Code Online (Sandbox Code Playgroud)

和,

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
Run Code Online (Sandbox Code Playgroud)


mjo*_*nor 5

像这样:

| sort-object {[int]($_.basename -replace '\D')}
Run Code Online (Sandbox Code Playgroud)


use*_*372 5

感谢您以上对我的问题提出的所有建议。在简化建议之后,以下代码适合我的情况。这有助于我像Windows资源管理器一样按自然顺序排序。

$ToNatural= { [regex]::Replace($_, '\d+',{$args[0].Value.Padleft(20)})}
$File= Get-ChildItem $FileLocation -Filter *.sql | Where-Object {$_.LastWriteTime -gt $datetime} | Sort-Object $ToNatural
Run Code Online (Sandbox Code Playgroud)