tl;dr:
Get-Item
isn't worth using with the env:
drive's root; to enumerate the current process' environment variables, use Get-ChildItem env:
instead.
Generally, use Get-Item
to get information about the targeted item itself, and Get-ChildItem
to get information about its children.
Get-Item
is designed to return a given item itself, whereas Get-ChildItem
returns its children.
Note: Get-ChildItem
falls back to the item itself for items that by definition cannot have children, such as individual environment variables or files - see bottom section.
Get-Item env:
is akin to Get-Item C:\
in that you're asking for the root of a PowerShell drive itself, not its children.
env:
is the PowerShell drive that contains all environment variables defined in the current process, and as itself it currently has a representation of limited utility, only accessing its children works as expected.
(Contrast this with a root directory such as C:\
, which has meaningful properties itself, such as timestamps, permissions, ...)
What PowerShell returns for the env:
drive is the collection of entries from the dictionary it uses to store information about the individual environment variables as a single object[1], which is usual behavior, in that commands are normally expected to send a collection's elements to the pipeline, one by one. That information about the item itself effectively includes the children too is unusual as well.
It is a moot point, because Get-ChildItem env:
will give you the same functionality in a conceptually clearer manner, but you could use (...)
, the grouping operator to force enumeration of the items in the collection that Get-Item env:
outputs:
# Currently the same as: Get-ChildItem env: | Sort-Object Name
(Get-Item env:) | Sort-Object Name
What would arguably more sense if PowerShell returned the whole dictionary rather than its collection of entries, so that you could access .Keys
to get all environment-variable names and .Values
to get all values. (Dictionaries / hashtables are not expected to be enumerated in PowerShell pipelines).
In fact, due to member-access enumeration, you could achieve the same effect by accessing properties .Key
and .Value
on the entry collection currently returned by 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*
"Sloppy" use of Get-ChildItem
As stated, for item types that by definition cannot have child items, Get-ChildItem
falls back to Get-Item
behavior, so that the following two commands are effectively equivalent:
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
However, it is conceptually preferable to use Get-Item
in such situations, given that it expresses the intent unambiguously.
As an aside: the commonly used $env:PATH
syntax for directly retrieving a given environment variable's value is an instance of namespace variable notation and is the equivalent of
Get-Content env:PATH
(not Get-Item
).
[1] Get-Item env:
returns the .Values
property value of the System.Collections.Generic.Dictionary`2
instance that PowerShell uses to store information about environment variables. That value is output as a single object, and its type is a collection type nested inside the dictionary type, System.Collections.Generic.Dictionary`2.ValueCollection
; you can inspect the type with Get-Item env: | Get-Member