PowerShell:按名称升序排序对象
PowerShell: Sort-Object by Name Ascending
PowerShell 似乎无法按名称正确升序对对象进行排序:
dir | Sort-Object Name
我的目标是按以下顺序对元素进行排序:
1.sql
2.sql
3.sql
...
9.sql
10.sql
11.sql
...
有办法解决吗?
您需要将文件名排序为数字,而不是文本。这很方便,因为您的示例中的文件名完全是数字,因此您可以更改排序以使用动态脚本块 属性,这会将文件名评估为管道中每个项目的数字:
| sort-object -Property {
if (($i = $_.BaseName -as [int])) { $i } else { $_ }
}
意思是:如果文件名可以转换为整数,则使用它,否则按原样使用。
对于包含在字母字符中的更复杂的模式,请使用 $ToNatural,它通过用零向左填充将所有嵌入的数字扩展到唯一长度(此处为 20)。
来源:Roman Kuzmin - How to sort by file name the same way Windows Explorer does?
$ToNatural = { [regex]::Replace($_, '\d+', { $args[0].Value.PadLeft(20,"0") }) }
生成一些测试数据:
> (10..11 + 100..101 + 1..2)|%{new-item -itemtype file -path ("pre_{0}_post.sql" -f $_)
Directory: A:\
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 2018-07-27 11:02 0 pre_10_post.sql
-a---- 2018-07-27 11:02 0 pre_11_post.sql
-a---- 2018-07-27 11:02 0 pre_100_post.sql
-a---- 2018-07-27 11:02 0 pre_101_post.sql
-a---- 2018-07-27 11:02 0 pre_1_post.sql
-a---- 2018-07-27 11:02 0 pre_2_post.sql
> dir| sort
Directory(: A:\
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 2018-07-27 11:02 0 pre_1_post.sql
-a---- 2018-07-27 11:02 0 pre_10_post.sql
-a---- 2018-07-27 11:02 0 pre_100_post.sql
-a---- 2018-07-27 11:02 0 pre_101_post.sql
-a---- 2018-07-27 11:02 0 pre_11_post.sql
-a---- 2018-07-27 11:02 0 pre_2_post.sql
> dir|sort $ToNatural
Directory: A:\
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 2018-07-27 11:02 0 pre_1_post.sql
-a---- 2018-07-27 11:02 0 pre_2_post.sql
-a---- 2018-07-27 11:02 0 pre_10_post.sql
-a---- 2018-07-27 11:02 0 pre_11_post.sql
-a---- 2018-07-27 11:02 0 pre_100_post.sql
-a---- 2018-07-27 11:02 0 pre_101_post.sql
PowerShell 似乎无法按名称正确升序对对象进行排序:
dir | Sort-Object Name
我的目标是按以下顺序对元素进行排序:
1.sql
2.sql
3.sql
...
9.sql
10.sql
11.sql
...
有办法解决吗?
您需要将文件名排序为数字,而不是文本。这很方便,因为您的示例中的文件名完全是数字,因此您可以更改排序以使用动态脚本块 属性,这会将文件名评估为管道中每个项目的数字:
| sort-object -Property {
if (($i = $_.BaseName -as [int])) { $i } else { $_ }
}
意思是:如果文件名可以转换为整数,则使用它,否则按原样使用。
对于包含在字母字符中的更复杂的模式,请使用 $ToNatural,它通过用零向左填充将所有嵌入的数字扩展到唯一长度(此处为 20)。
来源:Roman Kuzmin - How to sort by file name the same way Windows Explorer does?
$ToNatural = { [regex]::Replace($_, '\d+', { $args[0].Value.PadLeft(20,"0") }) }
生成一些测试数据:
> (10..11 + 100..101 + 1..2)|%{new-item -itemtype file -path ("pre_{0}_post.sql" -f $_)
Directory: A:\
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 2018-07-27 11:02 0 pre_10_post.sql
-a---- 2018-07-27 11:02 0 pre_11_post.sql
-a---- 2018-07-27 11:02 0 pre_100_post.sql
-a---- 2018-07-27 11:02 0 pre_101_post.sql
-a---- 2018-07-27 11:02 0 pre_1_post.sql
-a---- 2018-07-27 11:02 0 pre_2_post.sql
> dir| sort
Directory(: A:\
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 2018-07-27 11:02 0 pre_1_post.sql
-a---- 2018-07-27 11:02 0 pre_10_post.sql
-a---- 2018-07-27 11:02 0 pre_100_post.sql
-a---- 2018-07-27 11:02 0 pre_101_post.sql
-a---- 2018-07-27 11:02 0 pre_11_post.sql
-a---- 2018-07-27 11:02 0 pre_2_post.sql
> dir|sort $ToNatural
Directory: A:\
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 2018-07-27 11:02 0 pre_1_post.sql
-a---- 2018-07-27 11:02 0 pre_2_post.sql
-a---- 2018-07-27 11:02 0 pre_10_post.sql
-a---- 2018-07-27 11:02 0 pre_11_post.sql
-a---- 2018-07-27 11:02 0 pre_100_post.sql
-a---- 2018-07-27 11:02 0 pre_101_post.sql