Алфавитно-цифровая сортировка не работает в массиве - PullRequest
0 голосов
/ 05 августа 2020

У нас есть каталог, в котором есть множество подкаталогов (по одному в день) с серверами файлов в нем. К сожалению, файлы могут быть отправлены повторно, поэтому файл от 01.01.2020 можно повторно отправить (с немного другим именем, поскольку к имени файла добавлена ​​метка времени) 03.02.2020. Структура выглядит примерно так:

  • TopDir
    • 20200801
      • AFile_20200801_20200801150000 (с отметкой времени 2020-08-01 15:00:00)
      • BFile_20200801_20200801150000
      • CFile_20200801_20200801150000
    • 20200802
      • AFile_20200802_20200801150000

Таким образом, AFile от 2020-08-01 был повторно отправлен на 2020-08- 02 в 15:00.

Сейчас я пытаюсь получить список с самым последним файлом за день, поэтому я создал массив и заполнил его всеми файлами ниже 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:

  • AFile_20200801, AFile_20200801_20200801150000, ...
  • AFile_20200801, AFile_20200801_20200802150000, ...

Однако, когда я пытаюсь отсортировать свой массив (см. Код выше), вывод НЕ сортируется по имени. Вместо этого я получаю что-то вроде следующего:

  • AFile_20200801
  • CFile_20200802
  • AFile_20200801
  • BFile_20200801

What I хочу добиться сортировки по FileNameShort ASCENDING и LastWriteTime DESCENDING.

Что мне здесь не хватает?

Ответы [ 2 ]

1 голос
/ 05 августа 2020

Ваша сортировка не работает, потому что $FileArray - это массив таблиц ha sh. Синтаксис Sort FileNameShort связывает свойство FileNameShort с параметром -Property в Sort-Object. Однако таблица ha sh не содержит свойства с именем FileShortName. Вы можете увидеть это, если запустите $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

Кроме того, я не рекомендую использовать += для кажущегося добавления элементов в массив. Лучше всего либо вывести результаты внутри вашего l oop и сохранить результаты l oop, либо создать список с помощью метода .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 ++;
      }
    }
0 голосов
/ 05 августа 2020

Я только что нашел решение:

$FileArray = $FileArray | sort @{Expression={[string]$_.FileNameShort}; Ascending=$True}, @{Expression={[datetime]$_.LastWriteTime}; Descending=$True}

Тем не менее, я не знаю, почему первая сортировка не сработала должным образом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...