【问题标题】:Powershell script duplicate existing files inside destination folder while copying filesPowershell脚本在复制文件时复制目标文件夹中的现有文件
【发布时间】:2019-03-20 14:50:41
【问题描述】:

在下面的 Powershell 脚本中,我正在解压缩一个压缩文件夹,将另一个文件夹(从不同的路径)移动到这个解压缩文件夹的路径中。最后,将解压缩的文件夹拉回并删除我在此过程中创建的所有临时路径。它正在成功复制文件夹,但令我惊讶的是,解压缩文件夹中的现有文件正在重复。

请有人告诉我我在这里做错了什么吗?

if(Test-Path $Env:BUILD_SOURCESDIRECTORY/MyProject/WEB/dist)
{
    if(Test-Path $Env:BUILD_ArtifactStagingDirectory\MyProject.API.zip)
    {
        Expand-Archive -Path $Env:BUILD_ARTIFACTSTAGINGDIRECTORY\MyProject.API.zip -DestinationPath $Env:BUILD_SOURCESDIRECTORY\MyProject\API\temp -Force
        Write-Host "MyProject.API.zip folder unzipped successfully!"

        New-Item -ItemType Directory -Force -Path $Env:BUILD_SOURCESDIRECTORY\MyProject\WEB\temp1
        Write-Host "A temporary folder 'temp1' inside Web project sources directory created."

        New-Item -ItemType Directory -Force -Path $Env:BUILD_SOURCESDIRECTORY\MyProject\WEB\temp1\temp2
        Write-Host "A temporary folder 'temp2' inside temp1 created."

        Copy-Item $Env:BUILD_SOURCESDIRECTORY\MyProject\WEB\dist\* -Destination $Env:BUILD_SOURCESDIRECTORY\MyProject\WEB\temp1\temp2 -Recurse
        Write-Host "Web project dist folder content copied to the temp temp2 folder"

        Copy-Item -Path $Env:BUILD_SOURCESDIRECTORY\MyProject\WEB\temp1\* -Destination $(Get-ChildItem -Path $Env:BUILD_SOURCESDIRECTORY\MyProject\API\temp -Directory -Recurse | ? {$_.Basename -eq 'MyDestinationFolder'} | % { $_.FullName}) -Recurse -Force
        Write-Host "temp2 folder and its content copied to the 'MyDestinationFolder' folder of the unzipped folder."

        if(Test-Path $Env:BUILD_SOURCESDIRECTORY\MyProject\WEB\temp1)
        {
            Remove-Item -Recurse -Force $Env:BUILD_SOURCESDIRECTORY\MyProject\WEB\temp1
            Write-Host "Temporary temp1 folder deleted."
        }
        Compress-Archive -Path $Env:BUILD_SOURCESDIRECTORY\MyProject\API\temp\* -Update -DestinationPath $Env:BUILD_ARTIFACTSTAGINGDIRECTORY\MyProject.API.zip
        Write-Host "Unzipped folder is zipped back."

        Remove-Item -Recurse -Force $Env:BUILD_SOURCESDIRECTORY\MyProject\API\temp
        Write-Host "Temporary unzipped folder deleted."
    }
}

【问题讨论】:

  • 所以本质上,您需要解压 .zip,将文件复制到解压后的目录中,然后再将其重新压缩回来?
  • 这是真的@Matt
  • 您只是想将一个文件添加到 zip 中,还是添加多个文件?
  • 许多文件和文件夹。

标签: azure powershell azure-devops azure-pipelines


【解决方案1】:

就是这一行:

Compress-Archive -Path $Env:BUILD_SOURCESDIRECTORY\MyProject\API\temp\* -Update -DestinationPath $Env:BUILD_ARTIFACTSTAGINGDIRECTORY\MyProject.API.zip

您告诉它更新现有的 zip 文件,因此它会将项目添加到 zip 文件中 - 包括您在此处添加到 \API\temp 的内容:

Copy-Item -Path $Env:BUILD_SOURCESDIRECTORY\MyProject\WEB\temp1\* -Destination $(Get-ChildItem -Path $Env:BUILD_SOURCESDIRECTORY\MyProject\API\temp -Directory -Recurse | ? {$_.Basename -eq 'MyDestinationFolder'} | % { $_.FullName}) -Recurse -Force

基本上,创建一个新的 zip 文件或从您的 compress-archive cmdlet 中删除 -update。或者您可以检查文件是否存在,如果不存在 - 将其压缩。使用Test-Path cmdlet 进行检查。

【讨论】:

  • 删除 -Update 参数会导致使用 -Update 更新现有存档或 -Force 替换现有存档的错误。我已经尝试过 -Force 但最佳压缩级别导致我的 devops 发布管道出现问题,其中“IIS Web App Deploy”任务无法加载 zip 文件夹。
  • 如何制作一个新的 zip 文件,将 zip 上传到 Azure 工件并在 IIS Web App Deploy 任务中使用它?
  • 新的 zip 文件夹与 -Force 参数相同。已经尝试过了。找出“构建解决方案”任务用于创建构建工件的压缩类型会很好。
【解决方案2】:

所以你不需要解压MyProject.API.zip,然后添加文件,然后重新打包,以便将文件注入其中......你可以将“松散”文件添加到现有的.zip文件中就目前而言。

这是我测试它的方式:(您应该能够按照这些步骤来实现您想要完成的目标,我使用这些步骤是因为它们更容易遵循):

  • C:\testing\toAdd\FileToAdd.txt 创建了一个目录和文件(这模拟了我的文件 想注射)
  • C:\testing\zip\Zip.zip 创建了一个目录和 Zip 文件(这模拟了我的 .zip 文件所在的位置)
  • Zip.zip 文件中有 2 个文件:
    1. New Text Document 1.txt
    1. New Text Document 2.txt

我所要做的就是运行以下命令将FileToAdd.txt“注入”到Zip.zip

Compress-Archive -Path C:\testing\toAdd\* -DestinationPath C:\testing\zip\Zip.zip -Update

截图如下:


文件添加路径


目标 ZIP 文件路径和内容:


运行上述命令后Zip.zip的内容:


希望这会有所帮助!

【讨论】:

  • 这就是我已经在做的事情,它正在创建 MyDestinationFolder 中所有现有文件的副本。但是,从Copy-Item -Path $Env:BUILD_SOURCESDIRECTORY\MyProject\WEB\temp1\* 位置复制的任何文件或文件夹都不会重复。
  • 但这不是你正在做的。您显然是先解压缩 zip 文件。你不需要这样做。
【解决方案3】:

这是你可以尝试的其他东西..我为你写了这个函数..

Link to function can be found here.

function Add-ToZipFile {

    param(
        [Parameter(Mandatory)]
        [ValidateScript({
                    [System.IO.File]::Exists($_) -and [System.IO.FileInfo]::new($_).Extension -eq ".zip"

                    # YOU MUST SUPPLY AN EXISTING ZIP FILE PATH!!!
        })]
        [string]$ZipFilePath,

        [Parameter(Mandatory=$false)]
        [string[]]$FilesToAdd,

        [Parameter(Mandatory=$false)]
        [string[]]$FoldersToAdd
    )

    try {

        foreach($file in $FilesToAdd){
            if(Test-Path -Path $file -PathType Leaf) {
                Compress-Archive -Path $file -DestinationPath $ZipFilePath -Update
            } else {
                Write-Host "Unable to locate file: $($file) - Please make sure this file exists!" -f Red
            }
        }

        foreach($folder in $FoldersToAdd){
            if(Test-Path -Path $folder -PathType Container){
                $f = $folder.TrimEnd("\")
                $f = $f.TrimEnd("/")
                Compress-Archive -Path "$($f)" -DestinationPath $ZipFilePath -Update                             
            } else {
                Write-Host "Unable to locate folder: $($folder) - Please make sure this folder exists!" -f Red
            }
        }
    } catch {
        Write-Error "Something went wrong! Error: `r`n$($_)"    
    }
}

这里是如何使用它:

# MUST BE AN ARRAY OF STRINGS
# EVEN IF YOU HAVE A SINGLE PATH TO ADD, SURROUND IT IN '@( )' IN ORDER TO MAKE IT AN ARRAY
$files = @("C:\testing\SecondFileToAdd.txt")

# MUST BE AN ARRAY OF STRINGS 
$folders = @("C:\testing\toAdd", "C:\testing\anotherToAdd") 

# PATH TO ZIP FILE
$myZipPath = "C:\testing\zip\Zip.zip"

Add-ToZipFile -ZipFilePath $myZipPath -FilesToAdd $files -FoldersToAdd $folders

如果这不起作用,请告诉我(尽管在我的测试中它工作得很好)..

【讨论】:

  • 谢谢@Matt。我改变了我的构建管道。开始使用存档任务手动生成 zip,而不是构建时自动生成。