Edit zip file content in subfolder with Powershell

不想你离开。 提交于 2020-03-03 06:56:52

问题


I'm trying to update the contents of a zip file created from an Excel document. I want to replace some of the content of \zipfile\xl\connections.xml.

This partial script will list the contents of the zip file:

$shell_app = new-object -com shell.application
$zip = “$destination\exceltemplates\Templates\Template1.xlsx.zip”
$zip_file=$shell_app.NameSpace($zip)
$zip_file.Items() | Select Path

But every update method I've tried has generated an error. What's the next step needed to access and update a file in the zip file?


回答1:


This is not very complicated. Using PowerShell v3.0 or higher (and the standard .NET System.IO libraries) is easier.

# Parameters
$zipfileName = "E:\temp\WebsitePackage.zip"
$fileToEdit = "robots.txt"
$contents = "User-agent: *
Disallow: /"

# Open zip and find the particular file (assumes only one inside the Zip file)
Add-Type -assembly  System.IO.Compression.FileSystem
$zip =  [System.IO.Compression.ZipFile]::Open($zipfileName,"Update")
$robotsFile = $zip.Entries.Where({$_.name -eq $fileToEdit})

# Update the contents of the file
$desiredFile = [System.IO.StreamWriter]($robotsFile).Open()
$desiredFile.BaseStream.SetLength(0)
$desiredFile.Write($contents)
$desiredFile.Flush()
$desiredFile.Close()

# Write the changes and close the zip file
$zip.Dispose()
Write-Host "zip file updated"

The next problem is how to quickly check that your changes were successful? A simple adaptation of the script allows you to read the contents of file inside a Zip file:

# Parameters
$zipfileName = "E:\temp\WebsitePackage.zip"
$fileToRead = "robots.txt"

# Open zip and find the particular file (assumes only one inside the Zip file)
Add-Type -assembly  System.IO.Compression.FileSystem
$zip =  [System.IO.Compression.ZipFile]::Open($zipfileName,"Update")
$robotsFile = $zip.Entries.Where({$_.name -eq $fileToRead})

# Read the contents of the file
$desiredFile = [System.IO.StreamReader]($robotsFile).Open()
$text = $desiredFile.ReadToEnd()

# Output the contents
$text

$desiredFile.Close()
$desiredFile.Dispose()

# Close the zip file
$zip.Dispose()

There is useful background material at this article: https://mcpmag.com/articles/2014/09/29/file-frontier-part-6.aspx




回答2:


When searching, this is a question I found, so I thought I would venture to answer. In this generic script, the invocation of VB is not used, instead the dotnet import of System.IO.Compression.FileSystem. Hope this helps someone. Who knows, might even be me in the future! LOL

# The zip file to be updated
$file = Get-ChildItem ~\file.zip

# Load ZipFile (Compression.FileSystem) if necessary
try { $null = [IO.Compression.ZipFile] }
catch { [System.Reflection.Assembly]::LoadWithPartialName('System.IO.Compression.FileSystem') }

# Open zip file with update mode (Update, Read, Create -- are the options)
try { $fileZip = [System.IO.Compression.ZipFile]::Open( $file, 'Update' ) }
catch { throw "Another process has locked the '$file' file." }

# Finding the specific file within the zip file
<#
NOTE: These entries have the directories separated with a forward slash (/) instead of MS convention
of a backward slash (\).  Even though this is regex it seems the forward slash does not need to be escaped (\/).
NOTE2: Because this is regex '.*' must be used instead of a simple '*'
#>
$fileZip.Entries | Where-Object { $_.FullName -match '/subdir/.*/desiredfile.xml' }

# If needed, read the contents of specific file to $text and release the file so to use streamwriter later
$desiredFile = [System.IO.StreamReader]($fileZip.Entries | Where-Object { $_.FullName -match '/subdir/.*/desiredfile.xml' }).Open()
$text = $desiredFile.ReadToEnd()
$desiredFile.Close()
$desiredFile.Dispose()

# If needed, manipulate $text however for the update
$text = $text -replace '\n', [char]30

# Re-open the file this time with streamwriter
$desiredFile = [System.IO.StreamWriter]($fileZip.Entries | Where-Object { $_.FullName -match '/subdir/.*/desiredfile.xml' }).Open()

# If needed, zero out the file -- in case the new file is shorter than the old one
$desiredFile.BaseStream.SetLength(0)

# Insert the $text to the file and close
$desiredFile.Write($text -join "`r`n")
$desiredFile.Flush()
$desiredFile.Close()

# Write the changes and close the zip file
$fileZip.Dispose()



回答3:


I had to replace the version xml file (NuGetApp1.nuspec) in a zipped nuget package, like so:

Original file content in zip:

<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
  <metadata>
  <id>NuGetApp1</id>
  <version>1.1.3-dev22222</version>
  <title>NuGetApp1</title>
.....

Required :

<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
  <metadata>
  <id>NuGetApp1</id>
  <version>1.0.0.0</version>
  <title>NuGetApp1</title>
.....

Powershell Script:

$replaceWithVersion="1.0.0.0" 

$path = "c:\temp\testnuget"
$files = Get-ChildItem *.nupkg -Path $path 
foreach($fileNuget in $files)
{ 
    $target = $fileNuget.FullName -replace "[0-9]+(\.([0-9]+|\*)){1,4}", $replaceWithVersion
    Copy-Item $fileNuget.FullName -Destination $target
    $zipfileName = $target
    $fileToEdit = "*.nuspec"


    # Open zip and find the particular file (assumes only one inside the Zip file)
    $zip =  [System.IO.Compression.ZipFile]::Open($zipfileName,"Update")

    $nuspecFile = $zip.Entries.Where({$_.name -like $fileToEdit})

    # Read the contents of the file
    $desiredFile = [System.IO.StreamReader]($nuspecFile).Open()
    $text = $desiredFile.ReadToEnd()
    $desiredFile.Close()
    $desiredFile.Dispose()
    $text = $text -replace  '<version>[\s\S]*?<\/version>',"<version>$replaceWithVersion</version>"
    #update file with new content
    $desiredFile = [System.IO.StreamWriter]($nuspecFile).Open()
    $desiredFile.BaseStream.SetLength(0)

    # Insert the $text to the file and close
    $desiredFile.Write($text)
    $desiredFile.Flush()
    $desiredFile.Close()


   # Write the changes and close the zip file
   $zip.Dispose()
  Write-Host "zip file updated"
}

Happy hunting:-)!



来源:https://stackoverflow.com/questions/25538501/edit-zip-file-content-in-subfolder-with-powershell

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!