PowerShell: типы вывода Get-Item и Get-ChildItem

Я пытался распечатать переменные среды в алфавитном порядке (по имени), и первое, что я смог придумать, это:

Get-Item env: | Sort-Object -Property Name

Но вывод всегда был несортированным. Затем я попробовал следующее

Get-ChildItem env: | Sort-Object -Property Name

И получил ожидаемый, правильно отсортированный результат. Это говорит о том, что выводGet-Item а также Get-ChildItem не одного типа, даже если (отформатированный) вывод из Get-Item env: а также Get-ChildItem env: выглядит точно так же (т.е. словарь)

Передача вывода команд в | Get-TypeData показал, что Get-Item env: кажется, на самом деле возвращается только один System.Collections.DictionaryEntry, в то время как Get-ChildItem env: возвращает несколько System.Collections.DictionaryEntry объекты.

Может кто-нибудь объяснить, что именно здесь происходит? Почему два, казалось бы, разных типа входных данных создают идентичное внешнее представление вывода / строки? PowerShell неявно "распаковывает" объект словаря с одной записью изGet-Item выход?

Использование PowerShell 5.1 в Windows 10.

1 ответ

Решение

tl;dr:

  • Get-Item не стоит использовать с env:корень диска; чтобы перечислить переменные среды текущего процесса, используйтеGet-ChildItem env: вместо.

  • Как правило, используйте Get-Itemчтобы получить информацию о целевом пункте самого, иGet-ChildItemполучить информацию о своих детях.


Get-Itemпредназначен для возврата самого элемента, тогда какGet-ChildItemвозвращает своих детей.

Заметка: Get-ChildItem возвращается к самому элементу для элементов, которые по определению не могут иметь дочерних элементов, таких как отдельные переменные среды или файлы - см. нижний раздел.

Get-Item env: сродни Get-Item C:\в том, что вы просите за корень из PowerShell в привод сам, а не его дети.

env:это диск PowerShell, который содержит все переменные окружения, определенные в текущем процессе, и как сам он в настоящее время имеет представительства ограниченную полезность, только доступ к своим детям работает, как ожидалось. (Сравните это с корневым каталогом, таким какC:\, который сам имеет значимые свойства, такие как отметки времени, разрешения и т. д.)

Что PowerShell возвращает для env:диск - это набор записей из словаря, который он использует для хранения информации об отдельных переменных среды в виде единого объекта[1], что является обычным поведением, поскольку обычно ожидается, что команды будут отправлять элементы коллекции в конвейер один за другим.. Эта информация о самом предмете также включает детей.

Это спорный вопрос, потому что Get-ChildItem env: предоставит вам ту же функциональность в более понятной форме, но вы можете использовать (...), оператор группировки для принудительного перечисления элементов коллекции, которыеGet-Item env: выходы:

# Currently the same as: Get-ChildItem env: | Sort-Object Name
(Get-Item env:) | Sort-Object Name

Что, возможно, было бы лучше, если бы PowerShell вернул весь словарь, а не его коллекцию записей, чтобы вы могли получить доступ.Keysчтобы получить все имена переменных среды и.Valuesчтобы получить все значения. (Словари / хэш-таблицы не должны быть перечислены в конвейерах PowerShell).

Фактически, из-за перечисления членов вы можете добиться того же эффекта, получив доступ к свойствам.Key а также .Value в коллекции записей, возвращаемой в настоящее время Get-Item env:

(Get-Item env:).Name  # returns array of all env.-var. *names*; same as .Key 

(Get-Item env:).Value  # returns array of all *values*

"Небрежное" использование Get-ChildItem

Как уже говорилось, для типов элементов, которые по определению не могут иметь дочерние элементы, Get-ChildItem возвращается к Get-Item поведение, так что следующие две команды фактически эквивалентны:

Get-Item env:Path

# Same, because an environment variable can never have children,
# but it's better to use Get-Item.
Get-ChildItem env:Path

Однако концептуально предпочтительнее использовать Get-Itemв таких ситуациях, если однозначно выражает намерение.

В стороне: обычно используемые $env:PATHСинтаксис для непосредственного получения заданного переменного окружения в значении является экземпляром переменного пространства имен обозначений и является эквивалентом
Get-Content env:PATH (не Get-Item).


[1] Get-Item env: возвращает .Values стоимость собственности System.Collections.Generic.Dictionary`2 экземпляр, который PowerShell использует для хранения информации о переменных среды. Это значение выводится как один объект, и его тип представляет собой тип коллекции, вложенный в тип словаря, System.Collections.Generic.Dictionary`2.ValueCollection; вы можете проверить тип с помощьюGet-Item env: | Get-Member

Другие вопросы по тегам