1

我想运行这样的东西:

$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

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

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

$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
4

2 回答 2

2

扩展@nishaygoyal 的答案。在 PowerShell 中运行可执行文件(例如 docker)与在 CMD 提示符下运行可执行文件不同。在 PowerShell 中,参数作为字符串数组传递,而不是像在 CMD 提示符中那样以空格分隔的字符串系列传递。因此,通过传递空格分隔的参数字符串,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可以接受以空格分隔的参数列表,并以 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

在这种情况下,您可以看到它“正确”地拆分了参数

于 2020-05-27T23:24:11.500 回答
2

您定义它的方式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"
于 2020-05-27T23:04:05.303 回答