PowerShell Get-ChildItem результат в массиве

(Get-ChildItem -File -Recurse -Path $path).Fullname возвращает массив полных имен (Get-ChildItem -File -Recurse -Path $path).Name возвращает массив имен файлов, но (Get-ChildItem -File -Recurse -Path $path).Length возвращает только одно значение - количество элементов

Вопрос - как получить результат в виде массива длин файлов?

3 ответа

В дополнение к полезному ответу Матиаса Р. Джессена :

tl;dr

Использование позволяет получить краткое и эффективное решение:

      (Get-ChildItem -File -Recurse -Path $path).ForEach('Length')

Как указано в ответе Матиаса, свойства, присущие типу, например, в экземплярах массива, имеют приоритет над так называемым перечислением членов, которое было вашим намерением, то есть вы хотели собрать .Lengthзначения свойств элементов вашей коллекции (массива) и вернуть их как ( [object[]]) массив .

  • В выпуске GitHub № 7445 обсуждается эта ситуационная неоднозначность и предлагается ввести специального оператора , например %.так что вы можете однозначно запросить либо обычный доступ к свойству, либо перечисление членов.

Возможно, удивительным аспектом перечисления членов является то, что оно применяет конвейерную логику, которая ситуативно возвращает скаляр , а именно, если коллекция содержит только один элемент .

  • Например, @(Get-Date).Year.GetType().Name возвращает System.Int32, нет Object[], что указывает на то, что было возвращено целое число, а не (одноэлементный) массив, содержащий целое число.
  • обсуждается в Этовыпуске GitHub № 6802 .

Перечисление членов не только удобно, но и быстро , поскольку позволяет избежать цикла / перечисления в коде PowerShell .

Использование ForEach-Object или же Select-Object Командлеты , как показано в ответе Матиаса, определенно являются функциональным, но медленным решением из-за использования конвейера , который не требуется для ввода, который уже находится в памяти полностью .

Таким образом, использование в метода массивамассиве методом - с помощью перегрузки , где вы просто указать целевое свойство имя ( 'Length') - краткая и более эффективная альтернатива .

  • Примечание. В отличие от перечисления членов, возвращаемое значение из .ForEach()это всегда коллекция , хотя и не является массивом : он имеет тип [System.Collections.ObjectModel.Collection[psobject]], который, однако, в большинстве случаев будет вести себя как массив. [1]

[1] В отличие от массива, этот тип коллекции является расширяемой (вы можете добавлять или удалять элементы). Из-за того, что тип элемента [psobject], каждый элемент обычно невидимо заключен в этот тип; например, 42 -is [psobject] является $false, но @(42).ForEach({ $_ })[0] -is [psobject] является $true. К сожалению, бывают случаи, когда эта почти невидимая оболочка приводит к другому поведению - см. Проблему GitHub #5579.

Единственное значение, которое вы получаете, действительно является длиной результирующего массива - класс Array имеет явное свойство, которое имеет приоритет над перечислением свойств.

Чтобы получить человека Length значения свойств из каждого элемента в массиве, по конвейеру либо Select-Object или же ForEach-Object, вот так:

      Get-ChildItem -File -Recurse -Path $path |ForEach-Object -MemberName Length
# or 
Get-ChildItem -File -Recurse -Path $path |Select-Object -ExpandProperty Length

В вашем примере вы получаете результирующий массив.

Get-ChildItem -File возвращает массив System.IO.FileInfo. Итак, вам нужно взять (выбрать) атрибут каждой записи в массиве. Это делается с помощью Select-Object или просто select:

      Get-ChildItem -File -Recurse  -Path $path | Select-Object Length

который даст вам массив объектов, содержащих длину файла как Lengthимущество. Вы также можете выбрать несколько свойств:

      Get-ChildItem -File -Recurse  -Path $path | Select-Object Name, Length
Другие вопросы по тегам