Vaccano
Vaccano

Reputation: 82341

Powershell Variable replacement not working from command line

I have the following command I want to run from PowerShell:

docker run -v C:\src\docker_certs:/root/.dotnet/https -it MyContainer:MyTag /bin/bash

When I run that it works perfectly. (It mounts a volume using the source folder at the destination folder.)

But when I run this:

docker run -v $env:DOCKER_CERTS_PATH:/root/.dotnet/https -it MyContainer:MyTag /bin/bash

The volume does not get mounted.

I run this to check the value:

echo $env:DOCKER_CERTS_PATH

And it returns:

C:\src\docker_certs

As I understood things, it should have replaced the value of $env:DOCKER_CERTS_PATH with C:\src\docker_certs in the second command.

How can I get the PowerShell reference to an environment variable to replace when I run a command?

Upvotes: 1

Views: 404

Answers (1)

mklement0
mklement0

Reputation: 437618

Enclose the environment-variable reference in {...}:

docker run -v ${env:DOCKER_CERTS_PATH}:/root/.dotnet/https ...

Alternatively, `-escape the : char. following the env.-var. reference:

docker run -v $env:DOCKER_CERTS_PATH`:/root/.dotnet/https ...

As for what you tried:

docker run -v $env:DOCKER_CERTS_PATH:/root/.dotnet/https ...

If you don't use {...} to explicitly delineate a variable name, PowerShell may have a different idea of where the variable name ends than you do.

As an alternative to using {...}, you can `-escape the first character you don't want to be considered part of the variable name.

Note that your command argument is in this case implicitly treated as if it were enclosed in "...", so the above applies to expandable strings ("...") too.

For an comprehensive discussion of how unquoted tokens are parsed as command arguments, see this answer.

In the case at hand, the : that follows $env:DOCKER_CERTS_PATH is not considered the end of the variable reference; instead, it is considered part of the variable name, so that PowerShell looks for an environment variable (env:) literally named DOCKER_CERTS_PATH: (sic).

Since no such environment variable (presumably) exists, $env:DOCKER_CERTS_PATH: expands to the empty string and all that is passed to docker is /root/.dotnet/https.

You can verify that DOCKER_CERTS_PATH: is a valid environment variable name as follows:

PS> $env:DOCKER_CERTS_PATH: = 'hi'; $env:DOCKER_CERTS_PATH:
hi

By contrast, a regular (shell) variable is not permitted to contain :, because that : - in the absence of a namespace prefix such as env: - is itself considered a namespace prefix, which fails, because then the variable-name part is missing:

PS> $DOCKER_CERTS_PATH: = 'hi' # BREAKS, even with {...}
Variable reference is not valid. ':' was not followed by a valid variable name character. Consider using ${} to delimit the name.

The first : in a variable identifier is invariably considered the end of the namespace identifier, which must refer to an existing PowerShell drive name, as reported by Get-PSDrive. This notation is called namespace variable notation, as explained in this answer.

Upvotes: 3

Related Questions