【问题标题】:Docker cp parameter expansion in powershellpowershell中的docker cp参数扩展
【发布时间】:2020-05-27 21:50:57
【问题描述】:

我想运行这样的东西:

$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

【问题讨论】:

    标签: powershell docker docker-for-windows docker-cp


    【解决方案1】:

    扩展@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
    

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

    【讨论】:

    • 在您的数组示例中,变量$docker_container_name 未展开。我为第二个数组元素尝试了$docker_container_name + ":C:/docker_work/IAR/Debug",但看起来它正在分裂。
    • 这成功了:"$($docker_container_name):C:/docker_work/IAR/Debug",
    • 啊,是的,$docker_container_name:C: 被 PowerShell 解释为变量(为空),因此字符串扩展无法按预期“工作”。实际上,您必须使用子表达式运算符$(..) 将变量与字符串的其余部分正确分离,并正确进行字符串扩展。我已经用更正的代码编辑了答案。
    【解决方案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"
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-10-16
      • 1970-01-01
      • 2023-03-24
      • 2012-09-07
      • 2011-02-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多