-
Notifications
You must be signed in to change notification settings - Fork 8k
Description
Conceptually related: #4726.
Note: Fixing this issue would technically be a breaking change.
PowerShell treats the following:
${<drive>:<name>}
as if you had specified:
Get-Content -Path <drive>:<name> # or, with assignment, Set-Content -Path ...
This notation - though often used with the Env: drive (e.g., $env:Path) - is little-known as a general paradigm named namespace variable notation, which is explained in this SO answer.
The problem is the use of -Path rather than -LiteralPath (conceptually speaking), because -Path interprets its argument as a wildcard expression.
By design, you can only ever target a single item with namespace notation and if you intentionally specify a wildcard that resolves to multiple items, the statement breaks.
There is no good reason for namespace notation to treat paths as wildcard expressions to begin with, just as it makes no sense to do so for executable invocations and redirections (see #4726).
The fact that they are treated as wildcards causes problems with item names that happen to look like wildcard expressions, in one of two ways:
- You may not be able to create a new item, such as a new environment variable, at all.
- Perhaps worse, you may inadvertently target a different, preexisting item.
Taking the example of wanting to assign to / query the value of an environment variable literally named [foo] with ${env:[foo]}, from this SO question:
Steps to reproduce
# Try to create env. var. literally named '[foo]'
${env:[foo]} = 'bar'
# Create a seemingly unrelated env. var. whose name happens to match
# [foo] *if interpreted as a wildcard expression*
$env:o = 'no'
# Get the value
${env:[foo]}Expected behavior
bar
That is, implicit creation of the variable via namespace notation should succeed, as should subsequent retrieval.
Actual behavior
Cannot find path 'env:[foo]' because it does not exist.
no
-
That is, implicit creation of the variable failed, because the wildcard resolution of
[foo]matched nothing and so there was effectively no variable name to assign to / create. -
${env:[foo]}unexpectedly retrieved the value of${env:o}, because[foo]interpreted as a wildcard matcheso.
The workaround is to use double `-escaping: ${env:``[foo``]}; that the escape char. must be doubled is an additional quirk - see #7999
Environment data
PowerShell Core 6.2.0-rc.1
Windows PowerShell v5.1