PowerShell: типы вывода Get-Item и Get-ChildItem - PullRequest
2 голосов
/ 29 января 2020

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

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 Ответ

2 голосов
/ 29 января 2020

tl; др:

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

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


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

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

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

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

Что PowerShell возвращает для env: drive - это набор записей из словаря, который он использует для хранения информации об отдельных переменных среды как единый объект [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, чтобы получить все переменные среды names и .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 y значение экземпляра System.Collections.Generic.Dictionary`2, который PowerShell использует для хранения информации о переменных среды. Это значение выводится как отдельный объект, а его тип является типом коллекции, вложенным в тип словаря, System.Collections.Generic.Dictionary`2.ValueCollection; Вы можете проверить тип с помощью Get-Item env: | Get-Member

...