首页 > 解决方案 > 字母数字排序在数组中不起作用

问题描述

我们有一个目录,其中包含许多子目录(每天一个),其中包含多个文件。不幸的是,可以重新发送文件 - 因此可以在 2020 年 2 月 3 日重新发送 2020 年 1 月 1 日的文件(文件名略有不同,因为文件名中添加了时间戳)。结构看起来像这样:

因此 2020-08-01 的 AFile 已在 2020-08-02 下午 3 点重新发送。

我现在正在尝试检索包含每天最新文件的列表,因此我建立了一个数组并用 TopDir 下的所有文件(递归)填充它。到目前为止一切顺利,所有文件都找到了:

$path = "Y:\";

$FileArray = @()
$FileNameArray = @()

$FileArrayCounter = 0

foreach ($item in Get-ChildItem $path -Recurse)
    {
      if ($item.Extension -ne "")
      {
        $StringPart1, $StringPart2, $StringPart3, $StringPart4 = $item.Name.Split('_');
        $FileNameShort = "{0}_{1}_{2}" -f $StringPart1.Trim(), $StringPart2.Trim(), $StringPart3.Trim();
        $FileNameShort = $FileNameShort.Trim().ToUpper();

        $FileArray += @{FileID = $FileArrayCounter; FileNameShort = $FileNameShort; FileName = $item.Name; FullName = $item.FullName; LastWriteTime = $item.LastWriteTime};
        $FileArrayCounter ++;
      }
    }


$FileArray = $FileArray | sort FileNameShort; #@{Expression={"FileNameShort"}; Ascending=$True} #, @{Expression={"LastWriteTime"}; Descending=$True}

foreach($f in $FileArray)
{
    Write-host($f.FileNameShort, $f.LastWriteTime)
}

Write-host($FileArrayCounter.ToString() + " Dateien gefunden");

新添加的列“FileNameShort”包括文件名的子字符串。完成后,我收到两行AFile_20200801

但是,当我尝试对数组进行排序时(参见上面的代码),输出不是按名称排序的。相反,我收到如下内容:

我想要实现的是按 FileNameShort ASCENDING 和 LastWriteTime DESCENDING 排序。

我在这里想念什么?

标签: powershell

解决方案


您的排序不起作用,因为$FileArray它是一个哈希表数组。语法是将属性Sort FileNameShort绑定到 的参数。但是,哈希表不包含名为 的属性。如果你运行,你可以看到这一点。FileNameShort-PropertySort-ObjectFileShortName$FileArray[0] | Get-Member

如果您将它们创建为自定义对象,那么简单的排序语法就可以工作。

$FileArray += [pscustomobject]@{FileID = $FileArrayCounter; FileNameShort = $FileNameShort; FileName = $item.Name; FullName = $item.FullName; LastWriteTime = $item.LastWriteTime}
$FileArray | Sort FileNameShort # This will sort correctly

顺便说一句,我不建议使用+=看似将元素添加到数组中。最好在循环内输出结果并保存循环结果或使用.Add()方法创建列表。问题+=是当前数组被扩展到内存中,然后这些内容被用来创建一个包含新项目的新数组。随着阵列的增长,它的性能越来越差。请参阅下面的更有效的示例。

$FileArray = foreach ($item in Get-ChildItem $path -Recurse)
    {
      if ($item.Extension -ne "")
      {
        $StringPart1, $StringPart2, $StringPart3, $StringPart4 = $item.Name.Split('_');
        $FileNameShort = "{0}_{1}_{2}" -f $StringPart1.Trim(), $StringPart2.Trim(), $StringPart3.Trim();
        $FileNameShort = $FileNameShort.Trim().ToUpper();
        # Outputting custom object here
        [pscustomobject]@{FileID = $FileArrayCounter; FileNameShort = $FileNameShort; FileName = $item.Name; FullName = $item.FullName; LastWriteTime = $item.LastWriteTime};
        $FileArrayCounter ++;
      }
    }

推荐阅读