I was using tab autocompletion for a variable name in Powershell 5.1 today and noticed that one of the choices was the name of a PSDrive. The drive name is docs
What you're seeing is namespace variable notation, which is a variable-based way to access the content of items in PowerShell drives whose underlying provider implements content-based access (i.e., implements the IContentCmdletProvider interface).
The general syntax is:
${:} # same as: Get-Content :
${:} = ... # same as: Set-Content : -Value ...
The enclosing {...} aren't necessary if both the name and the can syntactically serve as a variable name; e.g.:
$env:HOME # no {...} needed
${env:ProgramFiles(x86)} # {...} needed due to "(" and ")"
In practice, as of Windows PowerShell v5.1, the following in-box drive providers support namespace variable notation:
Env:)Function:)Alias:)C:, ...)Variable:) - though virtually pointless, given that omitting the drive part accesses variables by default (e.g., $variable:HOME is the same as just $HOME).Of these, the Env: drive is by far the most frequently used with namespace variable notation, even though most users aren't aware of what underlies an environment-variable references such as $env:HOME.
On occasion you see it used with a filesystem drive - e.g., ${c:\foo\file.txt} - but the fact that you can only use literal paths and that you cannot control the character encoding limits its usefulness.
It allows interesting uses, however; e.g.:
PS> $alias:foreach # Get the definition of alias 'foreach'
ForEach-Object
PS> $function:prompt # Get the body of the 'prompt' function
"PS $($executionContext.SessionState.Path.CurrentLocation)$('>' * ($nestedPromptLevel + 1)) ";
# .Link
# https://go.microsoft.com/fwlink/?LinkID=225750
# .ExternalHelp System.Management.Automation.dll-help.xml
# Define a function foo that echoes 'hi' and invoke it.
PS> $function:foo = { 'hi' }; foo
hi
Note:
Because ${ and ${ are equivalent to Get-Content -Path and Set-Content -Path , paths are interpreted as wildcard expressions (because that's what -Path does, as opposed to -LiteralPath), which can cause problems with paths that look like wildcards - see this answer for an example and a workaround.
As of this writing, namespace variable notation isn't officially documented yet, but this GitHub issue suggests doing so.