Docker powershell中的cp参数扩展

Docker cp parameter expansion in powershell

我想要运行这样的东西:

$docker_container_name = "iar_build_container"
...
$cp_arguments =  $docker_container_name + ":C:/docker_work/IAR/Debug " + $docker_artifacts + "/Debug"

"Copying out the build artifacts: $cp_arguments"
docker cp "$cp_arguments"

这个输出是:

Copying out the build artifacts: iar_build_container:C:/docker_work/IAR/Debug ./docker_artifacts/Debug
"docker cp" requires exactly 2 arguments.
See 'docker cp --help'.

Usage:  docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|-
        docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH

Copy files/folders between a container and the local filesystem

如果我硬编码 docker cp 命令它会起作用,如果我使用以下命令它会起作用:

docker cp iar_build_container:C:/docker_work/IAR/Debug $docker_artifacts/Debug

所以我在扩展第一个参数(即容器名称和冒号)时遇到了问题。

编辑: 这行得通,但感觉很糟糕:

$cp_arguments = "cp " + $docker_container_name + ":C:/docker_work/IAR/Debug " + `
                        $docker_artifacts + "/Debug"

"Copying out the build artifacts: $cp_arguments"
Start-Process -FilePath "docker" -ArgumentList "$cp_arguments" -Wait

您定义它的方式,docker cp 实际上将 $cp_arguments 视为 1 个字符串,这就是它抱怨 2 个参数的原因请看下面

docker cp "iar_build_container:C:/docker_work/IAR/Debug $docker_artifacts/Debug"

如果您尝试以这种方式 运行 它将会失败。

尝试下面的方法,其中不将 "" 传递给 $cp_arguments

docker cp $cp_arguments

您已经在问题中定义了另一种方法,这有点老套,但还有一种方法。

$docker_container_name = "iar_build_container"
...
$cp_arguments_src =  $docker_container_name + ":C:/docker_work/IAR/Debug "
$cp_argument_dest =  $docker_artifacts + "/Debug"

"Copying out the build artifacts: $cp_arguments"
docker cp "$cp_arguments_src" "$cp_argument_dest"

扩展@nishaygoyal 的回答。 PowerShell 中的 运行 个可执行文件(例如 docker)不同于 CMD 提示符中的 运行 个可执行文件。在 PowerShell 中,参数作为 字符串数组 传递,而不是像在 CMD 提示符中那样作为 space 分隔的字符串系列传递。因此,通过传递 space 分隔的参数字符串,PowerShell 将其解释为单个参数和单个字符串。

因此,只需将您的参数更改为字符串数组,并将 "cp" 作为其中一项移动即可。一切正常:

$docker_container_name = "iar_build_container"
$docker_artifacts = "./docker_artifacts"

$cp_arguments = @("cp",                                               `
                  "$($docker_container_name):C:/docker_work/IAR/Debug",  `
                  "$docker_artifacts/Debug")

docker $cp_arguments

编辑:

正如@Nick 指出的那样,我们必须在字符串中使用子表达式运算符:$($docker_container_name) 来进行适当的字符串扩展,因为 PowerShell 会将 $docker_container_name:C: 解释为变量而不是 $docker_container_name.对于 PowerShell,冒号表示变量的范围,例如$global:foo。所以我们需要使用子表达式运算符 $() 来正确定义我们用于字符串扩展的变量。


为什么这样使用 Start-Process 有效?

$cp_arguments = "cp " + $docker_container_name + ":C:/docker_work/IAR/Debug " + `
                        $docker_artifacts + "/Debug"

Start-Process -FilePath "docker" -ArgumentList "$cp_arguments" -Wait

好吧,根据 Start-Process,它的特殊之处在于 -ArgumentList 可以接受 space 分隔的参数列表,并以 CMD 提示方式处理它们。

我们还可以使用 EchoArgs 来准确查看作为参数传递的内容:

$docker_container_name = "iar_build_container"
$docker_artifacts = "./docker_artifacts"

#Original:

$cp_arguments =  $docker_container_name + ":C:/docker_work/IAR/Debug " + $docker_artifacts + "/Debug"

PS C:\> EchoArgs.exe docker cp "$cp_arguments"
Arg 0 is <docker>
Arg 1 is <cp>
Arg 2 is <iar_build_container:C:/docker_work/IAR/Debug ./docker_artifacts/Debug>

Command line:
"C:\ProgramData\chocolatey\lib\echoargs\tools\EchoArgs.exe" docker cp "iar_build_container:C:/docker_work/IAR/Debug ./docker_artifacts/Debug"

(请注意,我们正在传递 2 个参数,cp,以及字符串的其余部分。与传递数组相比:

$cp_arguments = @("cp",                                               `
                  "$($docker_container_name):C:/docker_work/IAR/Debug",  `
                  "$docker_artifacts/Debug")

PS C:\> EchoArgs.exe docker $cp_arguments
Arg 0 is <docker>
Arg 1 is <cp>
Arg 2 is <iar_build_container:C:/docker_work/IAR/Debug>
Arg 3 is <./docker_artifacts/Debug>

Command line:
"C:\ProgramData\chocolatey\lib\echoargs\tools\EchoArgs.exe" docker cp iar_build_container:C:/docker_work/IAR/Debug ./docker_artifacts/Debug

在这种情况下,您可以看到它拆分了参数 "correctly"