Powershell Sort-Object带有数字的名称不正确

时间:2014-05-22 23:41:13

标签: .net powershell

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

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

现在,当我的命令尝试执行sort-object时,我看到顶部的Testscript10而不是TestScript5,我该如何解决这个问题?

我的代码"

$File= Get-ChildItem $FileLocation -Filter *.sql | Where-Object {$_.LastWriteTime -gt $datetime} | Sort-Object Name

$文件输出

[DBG]:PS SQLSERVER:>> $文件

Directory: C:\SQLScripts

模式LastWriteTime长度名称
---- ------------- ------ ----
-a --- 5/22/2014 10:20 AM 61 TestScript10.sql
-a --- 5/22/2014 10:16 AM 60 TestScript5.sql
-a --- 5/22/2014 10:24 AM 66 TestScript6.sql
-a --- 5/22/2014 10:10 AM 24 Testscript7.sql

4 个答案:

答案 0 :(得分: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

答案 1 :(得分:4)

这样的事情:

| sort-object {[int]($_.basename -replace '\D')}

答案 2 :(得分:2)

嗯...终于明白了。

Windows资源管理器在排序字符串时在shlwapi.dll中使用称为StrCmpLogicalW的遗留API,这就是我们看到不同排序结果的原因。

我不想使用padding零方法,所以写一个脚本。

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

由于我不是C#专家,因此赞赏拉请求。

查找以下powershell脚本,它使用相同的API。

function Sort-Naturally
{
    PARAM(
        [string[]]$strArray
    )

    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());
        }
    }
}
'@

    return [NaturalSort.NaturalSort]::Sort($strArray)
}

在下面找到测试结果。

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

PS> # Not good
PS> $t = (ls .\Scripts*.txt).name
PS> $t | Sort-Object
Scripts1.txt
Scripts10.txt
Scripts2.txt
PS> # Good
PS> Sort-Naturally -strArray $t
Scripts1.txt
Scripts2.txt
Scripts10.txt

答案 3 :(得分:0)

我更喜欢@mjolinor解决方案,因为它显示了PowerShell中排序的强大功能。但是,如果你想用注释中提到的前缀“修复”文件名:

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

重命名后,文件将按预期排序。如果您需要两位以上 - 只需更改格式化({0:D#})。